1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 14:18:12 +00:00

Kernel: Make copy_{from,to}_user() return KResult and use TRY()

This makes EFAULT propagation flow much more naturally. :^)
This commit is contained in:
Andreas Kling 2021-09-05 17:38:37 +02:00
parent 9903f5c6ef
commit 48a0b31c47
57 changed files with 318 additions and 551 deletions

View file

@ -476,10 +476,10 @@ Vector<FlatPtr> Processor::capture_stack_trace(Thread& thread, size_t max_frames
break; break;
if (Memory::is_user_range(VirtualAddress(stack_ptr), sizeof(FlatPtr) * 2)) { if (Memory::is_user_range(VirtualAddress(stack_ptr), sizeof(FlatPtr) * 2)) {
if (!copy_from_user(&retaddr, &((FlatPtr*)stack_ptr)[1]) || !retaddr) if (copy_from_user(&retaddr, &((FlatPtr*)stack_ptr)[1]).is_error() || !retaddr)
break; break;
stack_trace.append(retaddr); stack_trace.append(retaddr);
if (!copy_from_user(&stack_ptr, (FlatPtr*)stack_ptr)) if (copy_from_user(&stack_ptr, (FlatPtr*)stack_ptr).is_error())
break; break;
} else { } else {
void* fault_at; void* fault_at;
@ -552,7 +552,7 @@ Vector<FlatPtr> Processor::capture_stack_trace(Thread& thread, size_t max_frames
auto& regs = thread.regs(); auto& regs = thread.regs();
auto* stack_top = reinterpret_cast<FlatPtr*>(regs.sp()); auto* stack_top = reinterpret_cast<FlatPtr*>(regs.sp());
if (Memory::is_user_range(VirtualAddress(stack_top), sizeof(FlatPtr))) { if (Memory::is_user_range(VirtualAddress(stack_top), sizeof(FlatPtr))) {
if (!copy_from_user(&frame_ptr, &((FlatPtr*)stack_top)[0])) if (copy_from_user(&frame_ptr, &((FlatPtr*)stack_top)[0]).is_error())
frame_ptr = 0; frame_ptr = 0;
} else { } else {
void* fault_at; void* fault_at;

View file

@ -316,9 +316,7 @@ KResult KeyboardDevice::ioctl(FileDescription&, unsigned request, Userspace<void
switch (request) { switch (request) {
case KEYBOARD_IOCTL_GET_NUM_LOCK: { case KEYBOARD_IOCTL_GET_NUM_LOCK: {
auto output = static_ptr_cast<bool*>(arg); auto output = static_ptr_cast<bool*>(arg);
if (!copy_to_user(output, &m_num_lock_on)) return copy_to_user(output, &m_num_lock_on);
return EFAULT;
return KSuccess;
} }
case KEYBOARD_IOCTL_SET_NUM_LOCK: { case KEYBOARD_IOCTL_SET_NUM_LOCK: {
// In this case we expect the value to be a boolean and not a pointer. // In this case we expect the value to be a boolean and not a pointer.
@ -330,9 +328,7 @@ KResult KeyboardDevice::ioctl(FileDescription&, unsigned request, Userspace<void
} }
case KEYBOARD_IOCTL_GET_CAPS_LOCK: { case KEYBOARD_IOCTL_GET_CAPS_LOCK: {
auto output = static_ptr_cast<bool*>(arg); auto output = static_ptr_cast<bool*>(arg);
if (!copy_to_user(output, &m_caps_lock_on)) return copy_to_user(output, &m_caps_lock_on);
return EFAULT;
return KSuccess;
} }
case KEYBOARD_IOCTL_SET_CAPS_LOCK: { case KEYBOARD_IOCTL_SET_CAPS_LOCK: {
auto caps_lock_value = static_cast<u8>(arg.ptr()); auto caps_lock_value = static_cast<u8>(arg.ptr());

View file

@ -127,9 +127,7 @@ KResult SB16::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
switch (request) { switch (request) {
case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: { case SOUNDCARD_IOCTL_GET_SAMPLE_RATE: {
auto output = static_ptr_cast<u16*>(arg); auto output = static_ptr_cast<u16*>(arg);
if (!copy_to_user(output, &m_sample_rate)) return copy_to_user(output, &m_sample_rate);
return EFAULT;
return KSuccess;
} }
case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: { case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: {
auto sample_rate_value = static_cast<u16>(arg.ptr()); auto sample_rate_value = static_cast<u16>(arg.ptr());

View file

@ -317,9 +317,7 @@ KResult Inode::can_apply_flock(FileDescription const& description, flock const&
KResult Inode::apply_flock(Process const& process, FileDescription const& description, Userspace<flock const*> input_lock) KResult Inode::apply_flock(Process const& process, FileDescription const& description, Userspace<flock const*> input_lock)
{ {
flock new_lock = {}; flock new_lock = {};
if (!copy_from_user(&new_lock, input_lock)) TRY(copy_from_user(&new_lock, input_lock));
return EFAULT;
TRY(normalize_flock(description, new_lock)); TRY(normalize_flock(description, new_lock));
MutexLocker locker(m_inode_lock); MutexLocker locker(m_inode_lock);
@ -343,9 +341,7 @@ KResult Inode::apply_flock(Process const& process, FileDescription const& descri
KResult Inode::get_flock(FileDescription const& description, Userspace<flock*> reference_lock) const KResult Inode::get_flock(FileDescription const& description, Userspace<flock*> reference_lock) const
{ {
flock lookup = {}; flock lookup = {};
if (!copy_from_user(&lookup, reference_lock)) TRY(copy_from_user(&lookup, reference_lock));
return EFAULT;
TRY(normalize_flock(description, lookup)); TRY(normalize_flock(description, lookup));
MutexLocker locker(m_inode_lock, Mutex::Mode::Shared); MutexLocker locker(m_inode_lock, Mutex::Mode::Shared);
@ -356,16 +352,12 @@ KResult Inode::get_flock(FileDescription const& description, Userspace<flock*> r
if ((lookup.l_type == F_RDLCK && lock.type == F_WRLCK) || lookup.l_type == F_WRLCK) { if ((lookup.l_type == F_RDLCK && lock.type == F_WRLCK) || lookup.l_type == F_WRLCK) {
lookup = { lock.type, SEEK_SET, lock.start, lock.len, lock.pid }; lookup = { lock.type, SEEK_SET, lock.start, lock.len, lock.pid };
if (!copy_to_user(reference_lock, &lookup)) return copy_to_user(reference_lock, &lookup);
return EFAULT;
return KSuccess;
} }
} }
lookup.l_type = F_UNLCK; lookup.l_type = F_UNLCK;
if (!copy_to_user(reference_lock, &lookup)) return copy_to_user(reference_lock, &lookup);
return EFAULT;
return KSuccess;
} }
void Inode::remove_flocks_for_description(FileDescription const& description) void Inode::remove_flocks_for_description(FileDescription const& description)

View file

@ -64,24 +64,17 @@ KResult InodeFile::ioctl(FileDescription& description, unsigned request, Userspa
auto user_block_number = static_ptr_cast<int*>(arg); auto user_block_number = static_ptr_cast<int*>(arg);
int block_number = 0; int block_number = 0;
if (!copy_from_user(&block_number, user_block_number)) TRY(copy_from_user(&block_number, user_block_number));
return EFAULT;
if (block_number < 0) if (block_number < 0)
return EINVAL; return EINVAL;
auto block_address = TRY(inode().get_block_address(block_number)); auto block_address = TRY(inode().get_block_address(block_number));
if (!copy_to_user(user_block_number, &block_address)) return copy_to_user(user_block_number, &block_address);
return EFAULT;
return KSuccess;
} }
case FIONREAD: { case FIONREAD: {
int remaining_bytes = inode().size() - description.offset(); int remaining_bytes = inode().size() - description.offset();
if (!copy_to_user(Userspace<int*>(arg), &remaining_bytes)) return copy_to_user(Userspace<int*>(arg), &remaining_bytes);
return EFAULT;
return KSuccess;
} }
default: default:
return EINVAL; return EINVAL;

View file

@ -164,15 +164,12 @@ KResult FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
case FB_IOCTL_GET_SIZE_IN_BYTES: { case FB_IOCTL_GET_SIZE_IN_BYTES: {
auto user_size = static_ptr_cast<size_t*>(arg); auto user_size = static_ptr_cast<size_t*>(arg);
size_t value = framebuffer_size_in_bytes(); size_t value = framebuffer_size_in_bytes();
if (!copy_to_user(user_size, &value)) return copy_to_user(user_size, &value);
return EFAULT;
return KSuccess;
} }
case FB_IOCTL_GET_BUFFER: { case FB_IOCTL_GET_BUFFER: {
auto user_index = static_ptr_cast<int*>(arg); auto user_index = static_ptr_cast<int*>(arg);
int value = m_y_offset == 0 ? 0 : 1; int value = m_y_offset == 0 ? 0 : 1;
if (!copy_to_user(user_index, &value)) TRY(copy_to_user(user_index, &value));
return EFAULT;
if (!m_graphics_adapter->double_framebuffering_capable()) if (!m_graphics_adapter->double_framebuffering_capable())
return ENOTIMPL; return ENOTIMPL;
return KSuccess; return KSuccess;
@ -192,15 +189,12 @@ KResult FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
resolution.pitch = m_framebuffer_pitch; resolution.pitch = m_framebuffer_pitch;
resolution.width = m_framebuffer_width; resolution.width = m_framebuffer_width;
resolution.height = m_framebuffer_height; resolution.height = m_framebuffer_height;
if (!copy_to_user(user_resolution, &resolution)) return copy_to_user(user_resolution, &resolution);
return EFAULT;
return KSuccess;
} }
case FB_IOCTL_SET_RESOLUTION: { case FB_IOCTL_SET_RESOLUTION: {
auto user_resolution = static_ptr_cast<FBResolution*>(arg); auto user_resolution = static_ptr_cast<FBResolution*>(arg);
FBResolution resolution; FBResolution resolution;
if (!copy_from_user(&resolution, user_resolution)) TRY(copy_from_user(&resolution, user_resolution));
return EFAULT;
if (resolution.width > MAX_RESOLUTION_WIDTH || resolution.height > MAX_RESOLUTION_HEIGHT) if (resolution.width > MAX_RESOLUTION_WIDTH || resolution.height > MAX_RESOLUTION_HEIGHT)
return EINVAL; return EINVAL;
@ -208,8 +202,7 @@ KResult FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
resolution.pitch = m_framebuffer_pitch; resolution.pitch = m_framebuffer_pitch;
resolution.width = m_framebuffer_width; resolution.width = m_framebuffer_width;
resolution.height = m_framebuffer_height; resolution.height = m_framebuffer_height;
if (!copy_to_user(user_resolution, &resolution)) TRY(copy_to_user(user_resolution, &resolution));
return EFAULT;
return ENOTIMPL; return ENOTIMPL;
} }
@ -223,8 +216,7 @@ KResult FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
resolution.pitch = m_framebuffer_pitch; resolution.pitch = m_framebuffer_pitch;
resolution.width = m_framebuffer_width; resolution.width = m_framebuffer_width;
resolution.height = m_framebuffer_height; resolution.height = m_framebuffer_height;
if (!copy_to_user(user_resolution, &resolution)) TRY(copy_to_user(user_resolution, &resolution));
return EFAULT;
return EINVAL; return EINVAL;
} }
m_framebuffer_width = resolution.width; m_framebuffer_width = resolution.width;
@ -235,21 +227,16 @@ KResult FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
resolution.pitch = m_framebuffer_pitch; resolution.pitch = m_framebuffer_pitch;
resolution.width = m_framebuffer_width; resolution.width = m_framebuffer_width;
resolution.height = m_framebuffer_height; resolution.height = m_framebuffer_height;
if (!copy_to_user(user_resolution, &resolution)) return copy_to_user(user_resolution, &resolution);
return EFAULT;
return KSuccess;
} }
case FB_IOCTL_GET_BUFFER_OFFSET: { case FB_IOCTL_GET_BUFFER_OFFSET: {
auto user_buffer_offset = static_ptr_cast<FBBufferOffset*>(arg); auto user_buffer_offset = static_ptr_cast<FBBufferOffset*>(arg);
FBBufferOffset buffer_offset; FBBufferOffset buffer_offset;
if (!copy_from_user(&buffer_offset, user_buffer_offset)) TRY(copy_from_user(&buffer_offset, user_buffer_offset));
return EFAULT;
if (buffer_offset.buffer_index != 0 && buffer_offset.buffer_index != 1) if (buffer_offset.buffer_index != 0 && buffer_offset.buffer_index != 1)
return EINVAL; return EINVAL;
buffer_offset.offset = (size_t)buffer_offset.buffer_index * m_framebuffer_pitch * m_framebuffer_height; buffer_offset.offset = (size_t)buffer_offset.buffer_index * m_framebuffer_pitch * m_framebuffer_height;
if (!copy_to_user(user_buffer_offset, &buffer_offset)) return copy_to_user(user_buffer_offset, &buffer_offset);
return EFAULT;
return KSuccess;
} }
case FB_IOCTL_FLUSH_BUFFERS: case FB_IOCTL_FLUSH_BUFFERS:
return ENOTSUP; return ENOTSUP;

View file

@ -158,21 +158,16 @@ KResult FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
case FB_IOCTL_GET_SIZE_IN_BYTES: { case FB_IOCTL_GET_SIZE_IN_BYTES: {
auto out = static_ptr_cast<size_t*>(arg); auto out = static_ptr_cast<size_t*>(arg);
size_t value = m_buffer_size * 2; size_t value = m_buffer_size * 2;
if (!copy_to_user(out, &value)) return copy_to_user(out, &value);
return EFAULT;
return KSuccess;
} }
case FB_IOCTL_SET_RESOLUTION: { case FB_IOCTL_SET_RESOLUTION: {
auto user_resolution = static_ptr_cast<FBResolution*>(arg); auto user_resolution = static_ptr_cast<FBResolution*>(arg);
FBResolution resolution; FBResolution resolution;
if (!copy_from_user(&resolution, user_resolution)) TRY(copy_from_user(&resolution, user_resolution));
return EFAULT;
if (!try_to_set_resolution(resolution.width, resolution.height)) if (!try_to_set_resolution(resolution.width, resolution.height))
return EINVAL; return EINVAL;
resolution.pitch = pitch(); resolution.pitch = pitch();
if (!copy_to_user(user_resolution, &resolution)) return copy_to_user(user_resolution, &resolution);
return EFAULT;
return KSuccess;
} }
case FB_IOCTL_GET_RESOLUTION: { case FB_IOCTL_GET_RESOLUTION: {
auto user_resolution = static_ptr_cast<FBResolution*>(arg); auto user_resolution = static_ptr_cast<FBResolution*>(arg);
@ -180,9 +175,7 @@ KResult FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
resolution.pitch = pitch(); resolution.pitch = pitch();
resolution.width = width(); resolution.width = width();
resolution.height = height(); resolution.height = height();
if (!copy_to_user(user_resolution, &resolution)) return copy_to_user(user_resolution, &resolution);
return EFAULT;
return KSuccess;
} }
case FB_IOCTL_SET_BUFFER: { case FB_IOCTL_SET_BUFFER: {
auto buffer_index = static_cast<int>(arg.ptr()); auto buffer_index = static_cast<int>(arg.ptr());
@ -195,8 +188,7 @@ KResult FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
case FB_IOCTL_FLUSH_BUFFERS: { case FB_IOCTL_FLUSH_BUFFERS: {
auto user_flush_rects = static_ptr_cast<FBFlushRects*>(arg); auto user_flush_rects = static_ptr_cast<FBFlushRects*>(arg);
FBFlushRects flush_rects; FBFlushRects flush_rects;
if (!copy_from_user(&flush_rects, user_flush_rects)) TRY(copy_from_user(&flush_rects, user_flush_rects));
return EFAULT;
if (!is_valid_buffer_index(flush_rects.buffer_index)) if (!is_valid_buffer_index(flush_rects.buffer_index))
return EINVAL; return EINVAL;
if (Checked<unsigned>::multiplication_would_overflow(flush_rects.count, sizeof(FBRect))) if (Checked<unsigned>::multiplication_would_overflow(flush_rects.count, sizeof(FBRect)))
@ -206,8 +198,7 @@ KResult FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
MutexLocker locker(m_gpu.operation_lock()); MutexLocker locker(m_gpu.operation_lock());
for (unsigned i = 0; i < flush_rects.count; i++) { for (unsigned i = 0; i < flush_rects.count; i++) {
FBRect user_dirty_rect; FBRect user_dirty_rect;
if (!copy_from_user(&user_dirty_rect, &flush_rects.rects[i])) TRY(copy_from_user(&user_dirty_rect, &flush_rects.rects[i]));
return EFAULT;
Protocol::Rect dirty_rect { Protocol::Rect dirty_rect {
.x = user_dirty_rect.x, .x = user_dirty_rect.x,
.y = user_dirty_rect.y, .y = user_dirty_rect.y,
@ -238,14 +229,11 @@ KResult FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<v
case FB_IOCTL_GET_BUFFER_OFFSET: { case FB_IOCTL_GET_BUFFER_OFFSET: {
auto user_buffer_offset = static_ptr_cast<FBBufferOffset*>(arg); auto user_buffer_offset = static_ptr_cast<FBBufferOffset*>(arg);
FBBufferOffset buffer_offset; FBBufferOffset buffer_offset;
if (!copy_from_user(&buffer_offset, user_buffer_offset)) TRY(copy_from_user(&buffer_offset, user_buffer_offset));
return EFAULT;
if (!is_valid_buffer_index(buffer_offset.buffer_index)) if (!is_valid_buffer_index(buffer_offset.buffer_index))
return EINVAL; return EINVAL;
buffer_offset.offset = (size_t)buffer_offset.buffer_index * m_buffer_size; buffer_offset.offset = (size_t)buffer_offset.buffer_index * m_buffer_size;
if (!copy_to_user(user_buffer_offset, &buffer_offset)) return copy_to_user(user_buffer_offset, &buffer_offset);
return EFAULT;
return KSuccess;
} }
default: default:
return EINVAL; return EINVAL;

View file

@ -103,7 +103,7 @@ KResult IPv4Socket::bind(Userspace<const sockaddr*> user_address, socklen_t addr
return set_so_error(EINVAL); return set_so_error(EINVAL);
sockaddr_in address; sockaddr_in address;
if (!copy_from_user(&address, user_address, sizeof(sockaddr_in))) if (copy_from_user(&address, user_address, sizeof(sockaddr_in)).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
if (address.sin_family != AF_INET) if (address.sin_family != AF_INET)
@ -147,7 +147,7 @@ KResult IPv4Socket::connect(FileDescription& description, Userspace<const sockad
return set_so_error(EINVAL); return set_so_error(EINVAL);
u16 sa_family_copy; u16 sa_family_copy;
auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr()); auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr());
if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16))) if (copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16)).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
if (sa_family_copy != AF_INET) if (sa_family_copy != AF_INET)
return set_so_error(EINVAL); return set_so_error(EINVAL);
@ -155,7 +155,7 @@ KResult IPv4Socket::connect(FileDescription& description, Userspace<const sockad
return set_so_error(EISCONN); return set_so_error(EISCONN);
sockaddr_in safe_address; sockaddr_in safe_address;
if (!copy_from_user(&safe_address, (const sockaddr_in*)user_address, sizeof(sockaddr_in))) if (copy_from_user(&safe_address, (const sockaddr_in*)user_address, sizeof(sockaddr_in)).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
m_peer_address = IPv4Address((const u8*)&safe_address.sin_addr.s_addr); m_peer_address = IPv4Address((const u8*)&safe_address.sin_addr.s_addr);
@ -201,7 +201,7 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer&
if (addr) { if (addr) {
sockaddr_in ia; sockaddr_in ia;
if (!copy_from_user(&ia, Userspace<const sockaddr_in*>(addr.ptr()))) if (copy_from_user(&ia, Userspace<const sockaddr_in*>(addr.ptr())).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
if (ia.sin_family != AF_INET) { if (ia.sin_family != AF_INET) {
@ -360,12 +360,12 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti
out_addr.sin_port = htons(packet.peer_port); out_addr.sin_port = htons(packet.peer_port);
out_addr.sin_family = AF_INET; out_addr.sin_family = AF_INET;
Userspace<sockaddr_in*> dest_addr = addr.ptr(); Userspace<sockaddr_in*> dest_addr = addr.ptr();
if (!copy_to_user(dest_addr, &out_addr)) if (copy_to_user(dest_addr, &out_addr).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
socklen_t out_length = sizeof(sockaddr_in); socklen_t out_length = sizeof(sockaddr_in);
VERIFY(addr_length); VERIFY(addr_length);
if (!copy_to_user(addr_length, &out_length)) if (copy_to_user(addr_length, &out_length).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
} }
@ -383,7 +383,7 @@ KResultOr<size_t> IPv4Socket::recvfrom(FileDescription& description, UserOrKerne
{ {
if (user_addr_length) { if (user_addr_length) {
socklen_t addr_length; socklen_t addr_length;
if (!copy_from_user(&addr_length, user_addr_length.unsafe_userspace_ptr())) if (copy_from_user(&addr_length, user_addr_length.unsafe_userspace_ptr()).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
if (addr_length < sizeof(sockaddr_in)) if (addr_length < sizeof(sockaddr_in))
return set_so_error(EINVAL); return set_so_error(EINVAL);
@ -492,8 +492,7 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use
if (user_value_size < sizeof(int)) if (user_value_size < sizeof(int))
return EINVAL; return EINVAL;
int value; int value;
if (!copy_from_user(&value, static_ptr_cast<const int*>(user_value))) TRY(copy_from_user(&value, static_ptr_cast<const int*>(user_value)));
return EFAULT;
if (value < 0 || value > 255) if (value < 0 || value > 255)
return EINVAL; return EINVAL;
m_ttl = value; m_ttl = value;
@ -503,8 +502,7 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use
if (user_value_size != 1) if (user_value_size != 1)
return EINVAL; return EINVAL;
u8 value; u8 value;
if (!copy_from_user(&value, static_ptr_cast<const u8*>(user_value))) TRY(copy_from_user(&value, static_ptr_cast<const u8*>(user_value)));
return EFAULT;
if (value != 0 && value != 1) if (value != 0 && value != 1)
return EINVAL; return EINVAL;
m_multicast_loop = value; m_multicast_loop = value;
@ -514,8 +512,7 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use
if (user_value_size != sizeof(ip_mreq)) if (user_value_size != sizeof(ip_mreq))
return EINVAL; return EINVAL;
ip_mreq mreq; ip_mreq mreq;
if (!copy_from_user(&mreq, static_ptr_cast<const ip_mreq*>(user_value))) TRY(copy_from_user(&mreq, static_ptr_cast<const ip_mreq*>(user_value)));
return EFAULT;
if (mreq.imr_interface.s_addr != INADDR_ANY) if (mreq.imr_interface.s_addr != INADDR_ANY)
return ENOTSUP; return ENOTSUP;
IPv4Address address { (const u8*)&mreq.imr_multiaddr.s_addr }; IPv4Address address { (const u8*)&mreq.imr_multiaddr.s_addr };
@ -527,8 +524,7 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use
if (user_value_size != sizeof(ip_mreq)) if (user_value_size != sizeof(ip_mreq))
return EINVAL; return EINVAL;
ip_mreq mreq; ip_mreq mreq;
if (!copy_from_user(&mreq, static_ptr_cast<const ip_mreq*>(user_value))) TRY(copy_from_user(&mreq, static_ptr_cast<const ip_mreq*>(user_value)));
return EFAULT;
if (mreq.imr_interface.s_addr != INADDR_ANY) if (mreq.imr_interface.s_addr != INADDR_ANY)
return ENOTSUP; return ENOTSUP;
IPv4Address address { (const u8*)&mreq.imr_multiaddr.s_addr }; IPv4Address address { (const u8*)&mreq.imr_multiaddr.s_addr };
@ -546,28 +542,21 @@ KResult IPv4Socket::getsockopt(FileDescription& description, int level, int opti
return Socket::getsockopt(description, level, option, value, value_size); return Socket::getsockopt(description, level, option, value, value_size);
socklen_t size; socklen_t size;
if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) TRY(copy_from_user(&size, value_size.unsafe_userspace_ptr()));
return EFAULT;
switch (option) { switch (option) {
case IP_TTL: case IP_TTL:
if (size < sizeof(int)) if (size < sizeof(int))
return EINVAL; return EINVAL;
if (!copy_to_user(static_ptr_cast<int*>(value), (int*)&m_ttl)) TRY(copy_to_user(static_ptr_cast<int*>(value), (int*)&m_ttl));
return EFAULT;
size = sizeof(int); size = sizeof(int);
if (!copy_to_user(value_size, &size)) return copy_to_user(value_size, &size);
return EFAULT;
return KSuccess;
case IP_MULTICAST_LOOP: { case IP_MULTICAST_LOOP: {
if (size < 1) if (size < 1)
return EINVAL; return EINVAL;
if (!copy_to_user(static_ptr_cast<u8*>(value), (const u8*)&m_multicast_loop)) TRY(copy_to_user(static_ptr_cast<u8*>(value), (const u8*)&m_multicast_loop));
return EFAULT;
size = 1; size = 1;
if (!copy_to_user(value_size, &size)) return copy_to_user(value_size, &size);
return EFAULT;
return KSuccess;
} }
default: default:
return ENOPROTOOPT; return ENOPROTOOPT;
@ -581,8 +570,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
auto ioctl_route = [request, arg]() -> KResult { auto ioctl_route = [request, arg]() -> KResult {
auto user_route = static_ptr_cast<rtentry*>(arg); auto user_route = static_ptr_cast<rtentry*>(arg);
rtentry route; rtentry route;
if (!copy_from_user(&route, user_route)) TRY(copy_from_user(&route, user_route));
return EFAULT;
Userspace<const char*> user_rt_dev((FlatPtr)route.rt_dev); Userspace<const char*> user_rt_dev((FlatPtr)route.rt_dev);
auto ifname = TRY(try_copy_kstring_from_user(user_rt_dev, IFNAMSIZ)); auto ifname = TRY(try_copy_kstring_from_user(user_rt_dev, IFNAMSIZ));
@ -613,8 +601,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
auto ioctl_arp = [request, arg]() -> KResult { auto ioctl_arp = [request, arg]() -> KResult {
auto user_req = static_ptr_cast<arpreq*>(arg); auto user_req = static_ptr_cast<arpreq*>(arg);
arpreq arp_req; arpreq arp_req;
if (!copy_from_user(&arp_req, user_req)) TRY(copy_from_user(&arp_req, user_req));
return EFAULT;
switch (request) { switch (request) {
case SIOCSARP: case SIOCSARP:
@ -640,8 +627,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
auto ioctl_interface = [request, arg]() -> KResult { auto ioctl_interface = [request, arg]() -> KResult {
auto user_ifr = static_ptr_cast<ifreq*>(arg); auto user_ifr = static_ptr_cast<ifreq*>(arg);
ifreq ifr; ifreq ifr;
if (!copy_from_user(&ifr, user_ifr)) TRY(copy_from_user(&ifr, user_ifr));
return EFAULT;
char namebuf[IFNAMSIZ + 1]; char namebuf[IFNAMSIZ + 1];
memcpy(namebuf, ifr.ifr_name, IFNAMSIZ); memcpy(namebuf, ifr.ifr_name, IFNAMSIZ);
@ -673,9 +659,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
auto& socket_address_in = reinterpret_cast<sockaddr_in&>(ifr.ifr_addr); auto& socket_address_in = reinterpret_cast<sockaddr_in&>(ifr.ifr_addr);
socket_address_in.sin_family = AF_INET; socket_address_in.sin_family = AF_INET;
socket_address_in.sin_addr.s_addr = ip4_addr; socket_address_in.sin_addr.s_addr = ip4_addr;
if (!copy_to_user(user_ifr, &ifr)) return copy_to_user(user_ifr, &ifr);
return EFAULT;
return KSuccess;
} }
case SIOCGIFNETMASK: { case SIOCGIFNETMASK: {
@ -685,18 +669,14 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
// NOTE: NOT ifr_netmask. // NOTE: NOT ifr_netmask.
socket_address_in.sin_addr.s_addr = ip4_netmask; socket_address_in.sin_addr.s_addr = ip4_netmask;
if (!copy_to_user(user_ifr, &ifr)) return copy_to_user(user_ifr, &ifr);
return EFAULT;
return KSuccess;
} }
case SIOCGIFHWADDR: { case SIOCGIFHWADDR: {
auto mac_address = adapter->mac_address(); auto mac_address = adapter->mac_address();
ifr.ifr_hwaddr.sa_family = AF_INET; ifr.ifr_hwaddr.sa_family = AF_INET;
mac_address.copy_to(Bytes { ifr.ifr_hwaddr.sa_data, sizeof(ifr.ifr_hwaddr.sa_data) }); mac_address.copy_to(Bytes { ifr.ifr_hwaddr.sa_data, sizeof(ifr.ifr_hwaddr.sa_data) });
if (!copy_to_user(user_ifr, &ifr)) return copy_to_user(user_ifr, &ifr);
return EFAULT;
return KSuccess;
} }
case SIOCGIFBRDADDR: { case SIOCGIFBRDADDR: {
@ -707,9 +687,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
auto& socket_address_in = reinterpret_cast<sockaddr_in&>(ifr.ifr_addr); auto& socket_address_in = reinterpret_cast<sockaddr_in&>(ifr.ifr_addr);
socket_address_in.sin_family = AF_INET; socket_address_in.sin_family = AF_INET;
socket_address_in.sin_addr.s_addr = broadcast_addr; socket_address_in.sin_addr.s_addr = broadcast_addr;
if (!copy_to_user(user_ifr, &ifr)) return copy_to_user(user_ifr, &ifr);
return EFAULT;
return KSuccess;
} }
case SIOCGIFMTU: { case SIOCGIFMTU: {
@ -717,9 +695,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_family = AF_INET;
ifr.ifr_metric = ip4_metric; ifr.ifr_metric = ip4_metric;
if (!copy_to_user(user_ifr, &ifr)) return copy_to_user(user_ifr, &ifr);
return EFAULT;
return KSuccess;
} }
case SIOCGIFFLAGS: { case SIOCGIFFLAGS: {
@ -727,9 +703,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
constexpr short flags = 1; constexpr short flags = 1;
ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_family = AF_INET;
ifr.ifr_flags = flags; ifr.ifr_flags = flags;
if (!copy_to_user(user_ifr, &ifr)) return copy_to_user(user_ifr, &ifr);
return EFAULT;
return KSuccess;
} }
case SIOCGIFCONF: { case SIOCGIFCONF: {
@ -763,10 +737,7 @@ KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> a
case FIONREAD: { case FIONREAD: {
int readable = m_receive_buffer->immediately_readable(); int readable = m_receive_buffer->immediately_readable();
if (!copy_to_user(Userspace<int*>(arg), &readable)) return copy_to_user(Userspace<int*>(arg), &readable);
return EFAULT;
return KSuccess;
} }
} }
@ -791,4 +762,5 @@ void IPv4Socket::set_can_read(bool value)
if (value) if (value)
evaluate_block_conditions(); evaluate_block_conditions();
} }
} }

View file

@ -121,7 +121,7 @@ KResult LocalSocket::bind(Userspace<const sockaddr*> user_address, socklen_t add
return set_so_error(EINVAL); return set_so_error(EINVAL);
sockaddr_un address = {}; sockaddr_un address = {};
if (!copy_from_user(&address, user_address, sizeof(sockaddr_un))) if (copy_from_user(&address, user_address, sizeof(sockaddr_un)).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
if (address.sun_family != AF_LOCAL) if (address.sun_family != AF_LOCAL)
@ -162,7 +162,7 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka
return set_so_error(EINVAL); return set_so_error(EINVAL);
u16 sa_family_copy; u16 sa_family_copy;
auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr()); auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr());
if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16))) if (copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16)).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
if (sa_family_copy != AF_LOCAL) if (sa_family_copy != AF_LOCAL)
return set_so_error(EINVAL); return set_so_error(EINVAL);
@ -173,7 +173,7 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka
{ {
auto const& local_address = *reinterpret_cast<sockaddr_un const*>(user_address); auto const& local_address = *reinterpret_cast<sockaddr_un const*>(user_address);
char safe_address[sizeof(local_address.sun_path) + 1] = { 0 }; char safe_address[sizeof(local_address.sun_path) + 1] = { 0 };
if (!copy_from_user(&safe_address[0], &local_address.sun_path[0], sizeof(safe_address) - 1)) if (copy_from_user(&safe_address[0], &local_address.sun_path[0], sizeof(safe_address) - 1).is_error())
return set_so_error(EFAULT); return set_so_error(EFAULT);
safe_address[sizeof(safe_address) - 1] = '\0'; safe_address[sizeof(safe_address) - 1] = '\0';
maybe_path = KString::try_create(safe_address); maybe_path = KString::try_create(safe_address);
@ -398,8 +398,7 @@ KResult LocalSocket::getsockopt(FileDescription& description, int level, int opt
return Socket::getsockopt(description, level, option, value, value_size); return Socket::getsockopt(description, level, option, value, value_size);
socklen_t size; socklen_t size;
if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) TRY(copy_from_user(&size, value_size.unsafe_userspace_ptr()));
return EFAULT;
switch (option) { switch (option) {
case SO_SNDBUF: case SO_SNDBUF:
@ -411,18 +410,14 @@ KResult LocalSocket::getsockopt(FileDescription& description, int level, int opt
return EINVAL; return EINVAL;
switch (role(description)) { switch (role(description)) {
case Role::Accepted: case Role::Accepted:
if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_origin)) TRY(copy_to_user(static_ptr_cast<ucred*>(value), &m_origin));
return EFAULT;
size = sizeof(ucred); size = sizeof(ucred);
if (!copy_to_user(value_size, &size)) TRY(copy_to_user(value_size, &size));
return EFAULT;
return KSuccess; return KSuccess;
case Role::Connected: case Role::Connected:
if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_acceptor)) TRY(copy_to_user(static_ptr_cast<ucred*>(value), &m_acceptor));
return EFAULT;
size = sizeof(ucred); size = sizeof(ucred);
if (!copy_to_user(value_size, &size)) TRY(copy_to_user(value_size, &size));
return EFAULT;
return KSuccess; return KSuccess;
case Role::Connecting: case Role::Connecting:
return ENOTCONN; return ENOTCONN;
@ -441,10 +436,7 @@ KResult LocalSocket::ioctl(FileDescription& description, unsigned request, Users
switch (request) { switch (request) {
case FIONREAD: { case FIONREAD: {
int readable = receive_buffer_for(description)->immediately_readable(); int readable = receive_buffer_for(description)->immediately_readable();
if (!copy_to_user(Userspace<int*>(arg), &readable)) return copy_to_user(Userspace<int*>(arg), &readable);
return EFAULT;
return KSuccess;
} }
} }

View file

@ -128,8 +128,7 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va
return EINVAL; return EINVAL;
{ {
int timestamp; int timestamp;
if (!copy_from_user(&timestamp, static_ptr_cast<const int*>(user_value))) TRY(copy_from_user(&timestamp, static_ptr_cast<const int*>(user_value)));
return EFAULT;
m_timestamp = timestamp; m_timestamp = timestamp;
} }
if (m_timestamp && (domain() != AF_INET || type() == SOCK_STREAM)) { if (m_timestamp && (domain() != AF_INET || type() == SOCK_STREAM)) {
@ -147,8 +146,7 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va
KResult Socket::getsockopt(FileDescription&, int level, int option, Userspace<void*> value, Userspace<socklen_t*> value_size) KResult Socket::getsockopt(FileDescription&, int level, int option, Userspace<void*> value, Userspace<socklen_t*> value_size)
{ {
socklen_t size; socklen_t size;
if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) TRY(copy_from_user(&size, value_size.unsafe_userspace_ptr()));
return EFAULT;
// FIXME: Add TCP_NODELAY, IPPROTO_TCP and IPPROTO_IP (used in OpenSSH) // FIXME: Add TCP_NODELAY, IPPROTO_TCP and IPPROTO_IP (used in OpenSSH)
if (level != SOL_SOCKET) { if (level != SOL_SOCKET) {
@ -162,34 +160,26 @@ KResult Socket::getsockopt(FileDescription&, int level, int option, Userspace<vo
return EINVAL; return EINVAL;
{ {
timeval tv = m_send_timeout.to_timeval(); timeval tv = m_send_timeout.to_timeval();
if (!copy_to_user(static_ptr_cast<timeval*>(value), &tv)) TRY(copy_to_user(static_ptr_cast<timeval*>(value), &tv));
return EFAULT;
} }
size = sizeof(timeval); size = sizeof(timeval);
if (!copy_to_user(value_size, &size)) return copy_to_user(value_size, &size);
return EFAULT;
return KSuccess;
case SO_RCVTIMEO: case SO_RCVTIMEO:
if (size < sizeof(timeval)) if (size < sizeof(timeval))
return EINVAL; return EINVAL;
{ {
timeval tv = m_send_timeout.to_timeval(); timeval tv = m_send_timeout.to_timeval();
if (!copy_to_user(static_ptr_cast<timeval*>(value), &tv)) TRY(copy_to_user(static_ptr_cast<timeval*>(value), &tv));
return EFAULT;
} }
size = sizeof(timeval); size = sizeof(timeval);
if (!copy_to_user(value_size, &size)) return copy_to_user(value_size, &size);
return EFAULT;
return KSuccess;
case SO_ERROR: { case SO_ERROR: {
if (size < sizeof(int)) if (size < sizeof(int))
return EINVAL; return EINVAL;
int errno = so_error().error(); int errno = so_error().error();
if (!copy_to_user(static_ptr_cast<int*>(value), &errno)) TRY(copy_to_user(static_ptr_cast<int*>(value), &errno));
return EFAULT;
size = sizeof(int); size = sizeof(int);
if (!copy_to_user(value_size, &size)) TRY(copy_to_user(value_size, &size));
return EFAULT;
return set_so_error(KSuccess); return set_so_error(KSuccess);
} }
case SO_BINDTODEVICE: case SO_BINDTODEVICE:
@ -198,28 +188,21 @@ KResult Socket::getsockopt(FileDescription&, int level, int option, Userspace<vo
if (m_bound_interface) { if (m_bound_interface) {
const auto& name = m_bound_interface->name(); const auto& name = m_bound_interface->name();
auto length = name.length() + 1; auto length = name.length() + 1;
if (!copy_to_user(static_ptr_cast<char*>(value), name.characters(), length)) TRY(copy_to_user(static_ptr_cast<char*>(value), name.characters(), length));
return EFAULT;
size = length; size = length;
if (!copy_to_user(value_size, &size)) return copy_to_user(value_size, &size);
return EFAULT;
return KSuccess;
} else { } else {
size = 0; size = 0;
if (!copy_to_user(value_size, &size)) TRY(copy_to_user(value_size, &size));
return EFAULT; // FIXME: This return value looks suspicious.
return EFAULT; return EFAULT;
} }
case SO_TIMESTAMP: case SO_TIMESTAMP:
if (size < sizeof(int)) if (size < sizeof(int))
return EINVAL; return EINVAL;
if (!copy_to_user(static_ptr_cast<int*>(value), &m_timestamp)) TRY(copy_to_user(static_ptr_cast<int*>(value), &m_timestamp));
return EFAULT;
size = sizeof(int); size = sizeof(int);
if (!copy_to_user(value_size, &size)) return copy_to_user(value_size, &size);
return EFAULT;
return KSuccess;
default: default:
dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option); dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option);
return ENOPROTOOPT; return ENOPROTOOPT;

View file

@ -418,7 +418,7 @@ public:
KResultOr<FlatPtr> sys$map_time_page(); KResultOr<FlatPtr> sys$map_time_page();
template<bool sockname, typename Params> template<bool sockname, typename Params>
int get_sock_or_peer_name(const Params&); KResult get_sock_or_peer_name(Params const&);
static void initialize(); static void initialize();

View file

@ -45,7 +45,7 @@ Kernel::KResultOr<NonnullOwnPtr<Kernel::KString>> try_copy_kstring_from_user(Use
[[nodiscard]] Optional<Time> copy_time_from_user(const timespec* ts_user) [[nodiscard]] Optional<Time> copy_time_from_user(const timespec* ts_user)
{ {
timespec ts; timespec ts;
if (!copy_from_user(&ts, ts_user, sizeof(timespec))) { if (copy_from_user(&ts, ts_user, sizeof(timespec)).is_error()) {
return {}; return {};
} }
return Time::from_timespec(ts); return Time::from_timespec(ts);
@ -53,7 +53,7 @@ Kernel::KResultOr<NonnullOwnPtr<Kernel::KString>> try_copy_kstring_from_user(Use
[[nodiscard]] Optional<Time> copy_time_from_user(const timeval* tv_user) [[nodiscard]] Optional<Time> copy_time_from_user(const timeval* tv_user)
{ {
timeval tv; timeval tv;
if (!copy_from_user(&tv, tv_user, sizeof(timeval))) { if (copy_from_user(&tv, tv_user, sizeof(timeval)).is_error()) {
return {}; return {};
} }
return Time::from_timeval(tv); return Time::from_timeval(tv);
@ -168,57 +168,55 @@ Optional<u32> user_atomic_fetch_xor_relaxed(volatile u32* var, u32 val)
return Kernel::safe_atomic_fetch_xor_relaxed(var, val); return Kernel::safe_atomic_fetch_xor_relaxed(var, val);
} }
extern "C" { KResult copy_to_user(void* dest_ptr, void const* src_ptr, size_t n)
bool copy_to_user(void* dest_ptr, const void* src_ptr, size_t n)
{ {
bool is_user = Kernel::Memory::is_user_range(VirtualAddress(dest_ptr), n); if (!Kernel::Memory::is_user_range(VirtualAddress(dest_ptr), n))
if (!is_user) return EFAULT;
return false;
VERIFY(!Kernel::Memory::is_user_range(VirtualAddress(src_ptr), n)); VERIFY(!Kernel::Memory::is_user_range(VirtualAddress(src_ptr), n));
Kernel::SmapDisabler disabler; Kernel::SmapDisabler disabler;
void* fault_at; void* fault_at;
if (!Kernel::safe_memcpy(dest_ptr, src_ptr, n, fault_at)) { if (!Kernel::safe_memcpy(dest_ptr, src_ptr, n, fault_at)) {
VERIFY(VirtualAddress(fault_at) >= VirtualAddress(dest_ptr) && VirtualAddress(fault_at) <= VirtualAddress((FlatPtr)dest_ptr + n)); VERIFY(VirtualAddress(fault_at) >= VirtualAddress(dest_ptr) && VirtualAddress(fault_at) <= VirtualAddress((FlatPtr)dest_ptr + n));
dbgln("copy_to_user({:p}, {:p}, {}) failed at {}", dest_ptr, src_ptr, n, VirtualAddress { fault_at }); dbgln("copy_to_user({:p}, {:p}, {}) failed at {}", dest_ptr, src_ptr, n, VirtualAddress { fault_at });
return false; return EFAULT;
} }
return true; return KSuccess;
} }
bool copy_from_user(void* dest_ptr, const void* src_ptr, size_t n) KResult copy_from_user(void* dest_ptr, void const* src_ptr, size_t n)
{ {
bool is_user = Kernel::Memory::is_user_range(VirtualAddress(src_ptr), n); if (!Kernel::Memory::is_user_range(VirtualAddress(src_ptr), n))
if (!is_user) return EFAULT;
return false;
VERIFY(!Kernel::Memory::is_user_range(VirtualAddress(dest_ptr), n)); VERIFY(!Kernel::Memory::is_user_range(VirtualAddress(dest_ptr), n));
Kernel::SmapDisabler disabler; Kernel::SmapDisabler disabler;
void* fault_at; void* fault_at;
if (!Kernel::safe_memcpy(dest_ptr, src_ptr, n, fault_at)) { if (!Kernel::safe_memcpy(dest_ptr, src_ptr, n, fault_at)) {
VERIFY(VirtualAddress(fault_at) >= VirtualAddress(src_ptr) && VirtualAddress(fault_at) <= VirtualAddress((FlatPtr)src_ptr + n)); VERIFY(VirtualAddress(fault_at) >= VirtualAddress(src_ptr) && VirtualAddress(fault_at) <= VirtualAddress((FlatPtr)src_ptr + n));
dbgln("copy_from_user({:p}, {:p}, {}) failed at {}", dest_ptr, src_ptr, n, VirtualAddress { fault_at }); dbgln("copy_from_user({:p}, {:p}, {}) failed at {}", dest_ptr, src_ptr, n, VirtualAddress { fault_at });
return false; return EFAULT;
} }
return true; return KSuccess;
} }
const void* memmem(const void* haystack, size_t haystack_length, const void* needle, size_t needle_length) [[nodiscard]] KResult memset_user(void* dest_ptr, int c, size_t n)
{
return AK::memmem(haystack, haystack_length, needle, needle_length);
}
[[nodiscard]] bool memset_user(void* dest_ptr, int c, size_t n)
{ {
bool is_user = Kernel::Memory::is_user_range(VirtualAddress(dest_ptr), n); bool is_user = Kernel::Memory::is_user_range(VirtualAddress(dest_ptr), n);
if (!is_user) if (!is_user)
return false; return EFAULT;
Kernel::SmapDisabler disabler; Kernel::SmapDisabler disabler;
void* fault_at; void* fault_at;
if (!Kernel::safe_memset(dest_ptr, c, n, fault_at)) { if (!Kernel::safe_memset(dest_ptr, c, n, fault_at)) {
dbgln("memset_user({:p}, {}, {}) failed at {}", dest_ptr, c, n, VirtualAddress { fault_at }); dbgln("memset_user({:p}, {}, {}) failed at {}", dest_ptr, c, n, VirtualAddress { fault_at });
return false; return EFAULT;
} }
return true; return KSuccess;
}
extern "C" {
const void* memmem(const void* haystack, size_t haystack_length, const void* needle, size_t needle_length)
{
return AK::memmem(haystack, haystack_length, needle, needle_length);
} }
size_t strnlen(const char* str, size_t maxlen) size_t strnlen(const char* str, size_t maxlen)

View file

@ -34,11 +34,11 @@ template<typename T>
[[nodiscard]] Optional<u32> user_atomic_fetch_or_relaxed(volatile u32* var, u32 val); [[nodiscard]] Optional<u32> user_atomic_fetch_or_relaxed(volatile u32* var, u32 val);
[[nodiscard]] Optional<u32> user_atomic_fetch_xor_relaxed(volatile u32* var, u32 val); [[nodiscard]] Optional<u32> user_atomic_fetch_xor_relaxed(volatile u32* var, u32 val);
extern "C" { [[nodiscard]] KResult copy_to_user(void*, const void*, size_t);
[[nodiscard]] KResult copy_from_user(void*, const void*, size_t);
[[nodiscard]] KResult memset_user(void*, int, size_t);
[[nodiscard]] bool copy_to_user(void*, const void*, size_t); extern "C" {
[[nodiscard]] bool copy_from_user(void*, const void*, size_t);
[[nodiscard]] bool memset_user(void*, int, size_t);
void* memcpy(void*, const void*, size_t); void* memcpy(void*, const void*, size_t);
[[nodiscard]] int strncmp(const char* s1, const char* s2, size_t n); [[nodiscard]] int strncmp(const char* s1, const char* s2, size_t n);
@ -56,114 +56,114 @@ const void* memmem(const void* haystack, size_t, const void* needle, size_t);
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_from_user(T* dest, const T* src) [[nodiscard]] inline KResult copy_from_user(T* dest, const T* src)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src, sizeof(T)); return copy_from_user(dest, src, sizeof(T));
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_to_user(T* dest, const T* src) [[nodiscard]] inline KResult copy_to_user(T* dest, const T* src)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
return copy_to_user(dest, src, sizeof(T)); return copy_to_user(dest, src, sizeof(T));
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_from_user(T* dest, Userspace<const T*> src) [[nodiscard]] inline KResult copy_from_user(T* dest, Userspace<const T*> src)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T)); return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T));
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_from_user(T* dest, Userspace<T*> src) [[nodiscard]] inline KResult copy_from_user(T* dest, Userspace<T*> src)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T)); return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T));
} }
#define DEPRECATE_COPY_FROM_USER_TYPE(T, REPLACEMENT) \ #define DEPRECATE_COPY_FROM_USER_TYPE(T, REPLACEMENT) \
template<> \ template<> \
[[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) bool copy_from_user<T>(T*, const T*) \ [[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) KResult copy_from_user<T>(T*, const T*) \
{ \ { \
VERIFY_NOT_REACHED(); \ VERIFY_NOT_REACHED(); \
} \ } \
template<> \ template<> \
[[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) bool copy_from_user<T>(T*, Userspace<const T*>) \ [[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) KResult copy_from_user<T>(T*, Userspace<const T*>) \
{ \ { \
VERIFY_NOT_REACHED(); \ VERIFY_NOT_REACHED(); \
} \ } \
template<> \ template<> \
[[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) bool copy_from_user<T>(T*, Userspace<T*>) \ [[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) KResult copy_from_user<T>(T*, Userspace<T*>) \
{ \ { \
VERIFY_NOT_REACHED(); \ VERIFY_NOT_REACHED(); \
} }
DEPRECATE_COPY_FROM_USER_TYPE(timespec, copy_time_from_user) DEPRECATE_COPY_FROM_USER_TYPE(timespec, copy_time_from_user)
DEPRECATE_COPY_FROM_USER_TYPE(timeval, copy_time_from_user) DEPRECATE_COPY_FROM_USER_TYPE(timeval, copy_time_from_user)
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_to_user(Userspace<T*> dest, const T* src) [[nodiscard]] inline KResult copy_to_user(Userspace<T*> dest, const T* src)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
return copy_to_user(dest.unsafe_userspace_ptr(), src, sizeof(T)); return copy_to_user(dest.unsafe_userspace_ptr(), src, sizeof(T));
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_to_user(Userspace<T*> dest, const void* src, size_t size) [[nodiscard]] inline KResult copy_to_user(Userspace<T*> dest, const void* src, size_t size)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
return copy_to_user(dest.unsafe_userspace_ptr(), src, size); return copy_to_user(dest.unsafe_userspace_ptr(), src, size);
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_from_user(void* dest, Userspace<const T*> src, size_t size) [[nodiscard]] inline KResult copy_from_user(void* dest, Userspace<const T*> src, size_t size)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src.unsafe_userspace_ptr(), size); return copy_from_user(dest, src.unsafe_userspace_ptr(), size);
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_n_from_user(T* dest, const T* src, size_t count) [[nodiscard]] inline KResult copy_n_from_user(T* dest, const T* src, size_t count)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
Checked<size_t> size = sizeof(T); Checked<size_t> size = sizeof(T);
size *= count; size *= count;
if (size.has_overflow()) if (size.has_overflow())
return false; return EOVERFLOW;
return copy_from_user(dest, src, size.value()); return copy_from_user(dest, src, size.value());
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_n_to_user(T* dest, const T* src, size_t count) [[nodiscard]] inline KResult copy_n_to_user(T* dest, const T* src, size_t count)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
Checked<size_t> size = sizeof(T); Checked<size_t> size = sizeof(T);
size *= count; size *= count;
if (size.has_overflow()) if (size.has_overflow())
return false; return EOVERFLOW;
return copy_to_user(dest, src, size.value()); return copy_to_user(dest, src, size.value());
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_n_from_user(T* dest, Userspace<const T*> src, size_t count) [[nodiscard]] inline KResult copy_n_from_user(T* dest, Userspace<const T*> src, size_t count)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
Checked<size_t> size = sizeof(T); Checked<size_t> size = sizeof(T);
size *= count; size *= count;
if (size.has_overflow()) if (size.has_overflow())
return false; return EOVERFLOW;
return copy_from_user(dest, src.unsafe_userspace_ptr(), size.value()); return copy_from_user(dest, src.unsafe_userspace_ptr(), size.value());
} }
template<typename T> template<typename T>
[[nodiscard]] inline bool copy_n_to_user(Userspace<T*> dest, const T* src, size_t count) [[nodiscard]] inline KResult try_copy_n_to_user(Userspace<T*> dest, const T* src, size_t count)
{ {
static_assert(IsTriviallyCopyable<T>); static_assert(IsTriviallyCopyable<T>);
Checked<size_t> size = sizeof(T); Checked<size_t> size = sizeof(T);
size *= count; size *= count;
if (size.has_overflow()) if (size.has_overflow())
return false; return EOVERFLOW;
return copy_to_user(dest.unsafe_userspace_ptr(), src, size.value()); return copy_to_user(dest.unsafe_userspace_ptr(), src, size.value());
} }

View file

@ -52,8 +52,7 @@ KResultOr<FlatPtr> Process::sys$getcwd(Userspace<char*> buffer, size_t size)
size_t ideal_size = path.length() + 1; size_t ideal_size = path.length() + 1;
auto size_to_copy = min(ideal_size, size); auto size_to_copy = min(ideal_size, size);
if (!copy_to_user(buffer, path.characters(), size_to_copy)) TRY(copy_to_user(buffer, path.characters(), size_to_copy));
return EFAULT;
// Note: we return the whole size here, not the copied size. // Note: we return the whole size here, not the copied size.
return ideal_size; return ideal_size;
} }

View file

@ -24,8 +24,7 @@ KResultOr<FlatPtr> Process::sys$chown(Userspace<const Syscall::SC_chown_params*>
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
REQUIRE_PROMISE(chown); REQUIRE_PROMISE(chown);
Syscall::SC_chown_params params; Syscall::SC_chown_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto path = TRY(get_syscall_path_argument(params.path)); auto path = TRY(get_syscall_path_argument(params.path));
return VirtualFileSystem::the().chown(path->view(), params.uid, params.gid, current_directory()); return VirtualFileSystem::the().chown(path->view(), params.uid, params.gid, current_directory());
} }

View file

@ -37,10 +37,7 @@ KResultOr<FlatPtr> Process::sys$clock_gettime(clockid_t clock_id, Userspace<time
return EINVAL; return EINVAL;
auto ts = TimeManagement::the().current_time(clock_id).to_timespec(); auto ts = TimeManagement::the().current_time(clock_id).to_timespec();
if (!copy_to_user(user_ts, &ts)) return copy_to_user(user_ts, &ts);
return EFAULT;
return 0;
} }
KResultOr<FlatPtr> Process::sys$clock_settime(clockid_t clock_id, Userspace<const timespec*> user_ts) KResultOr<FlatPtr> Process::sys$clock_settime(clockid_t clock_id, Userspace<const timespec*> user_ts)
@ -71,8 +68,7 @@ KResultOr<FlatPtr> Process::sys$clock_nanosleep(Userspace<const Syscall::SC_cloc
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
Syscall::SC_clock_nanosleep_params params; Syscall::SC_clock_nanosleep_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
Optional<Time> requested_sleep = copy_time_from_user(params.requested_sleep); Optional<Time> requested_sleep = copy_time_from_user(params.requested_sleep);
if (!requested_sleep.has_value()) if (!requested_sleep.has_value())
@ -100,8 +96,9 @@ KResultOr<FlatPtr> Process::sys$clock_nanosleep(Userspace<const Syscall::SC_cloc
Time remaining_sleep; Time remaining_sleep;
was_interrupted = Thread::current()->sleep(params.clock_id, requested_sleep.value(), &remaining_sleep).was_interrupted(); was_interrupted = Thread::current()->sleep(params.clock_id, requested_sleep.value(), &remaining_sleep).was_interrupted();
timespec remaining_sleep_ts = remaining_sleep.to_timespec(); timespec remaining_sleep_ts = remaining_sleep.to_timespec();
if (was_interrupted && params.remaining_sleep && !copy_to_user(params.remaining_sleep, &remaining_sleep_ts)) if (was_interrupted && params.remaining_sleep) {
return EFAULT; TRY(copy_to_user(params.remaining_sleep, &remaining_sleep_ts));
}
} }
if (was_interrupted) if (was_interrupted)
return EINTR; return EINTR;
@ -115,8 +112,7 @@ KResultOr<FlatPtr> Process::sys$adjtime(Userspace<const timeval*> user_delta, Us
timespec old_delta_ts = TimeManagement::the().remaining_epoch_time_adjustment(); timespec old_delta_ts = TimeManagement::the().remaining_epoch_time_adjustment();
timeval old_delta; timeval old_delta;
timespec_to_timeval(old_delta_ts, old_delta); timespec_to_timeval(old_delta_ts, old_delta);
if (!copy_to_user(user_old_delta, &old_delta)) TRY(copy_to_user(user_old_delta, &old_delta));
return EFAULT;
} }
if (user_delta) { if (user_delta) {

View file

@ -33,8 +33,7 @@ KResultOr<FlatPtr> Process::sys$dbgputstr(Userspace<const char*> characters, siz
if (size <= 1024) { if (size <= 1024) {
char buffer[1024]; char buffer[1024];
if (!copy_from_user(buffer, characters, size)) TRY(copy_from_user(buffer, characters, size));
return EFAULT;
dbgputstr(buffer, size); dbgputstr(buffer, size);
return size; return size;
} }

View file

@ -79,19 +79,22 @@ static KResultOr<FlatPtr> make_userspace_context_for_main_thread([[maybe_unused]
auto push_on_new_stack = [&new_sp](FlatPtr value) { auto push_on_new_stack = [&new_sp](FlatPtr value) {
new_sp -= sizeof(FlatPtr); new_sp -= sizeof(FlatPtr);
Userspace<FlatPtr*> stack_ptr = new_sp; Userspace<FlatPtr*> stack_ptr = new_sp;
return copy_to_user(stack_ptr, &value); auto result = copy_to_user(stack_ptr, &value);
VERIFY(result.is_success());
}; };
auto push_aux_value_on_new_stack = [&new_sp](auxv_t value) { auto push_aux_value_on_new_stack = [&new_sp](auxv_t value) {
new_sp -= sizeof(auxv_t); new_sp -= sizeof(auxv_t);
Userspace<auxv_t*> stack_ptr = new_sp; Userspace<auxv_t*> stack_ptr = new_sp;
return copy_to_user(stack_ptr, &value); auto result = copy_to_user(stack_ptr, &value);
VERIFY(result.is_success());
}; };
auto push_string_on_new_stack = [&new_sp](const String& string) { auto push_string_on_new_stack = [&new_sp](const String& string) {
new_sp -= round_up_to_power_of_two(string.length() + 1, sizeof(FlatPtr)); new_sp -= round_up_to_power_of_two(string.length() + 1, sizeof(FlatPtr));
Userspace<FlatPtr*> stack_ptr = new_sp; Userspace<FlatPtr*> stack_ptr = new_sp;
return copy_to_user(stack_ptr, string.characters(), string.length() + 1); auto result = copy_to_user(stack_ptr, string.characters(), string.length() + 1);
VERIFY(result.is_success());
}; };
Vector<FlatPtr> argv_entries; Vector<FlatPtr> argv_entries;
@ -329,7 +332,7 @@ static KResultOr<LoadResult> load_elf_object(NonnullOwnPtr<Memory::AddressSpace>
master_tls_size = program_header.size_in_memory(); master_tls_size = program_header.size_in_memory();
master_tls_alignment = program_header.alignment(); master_tls_alignment = program_header.alignment();
if (!copy_to_user(master_tls_region->vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image())) { if (copy_to_user(master_tls_region->vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image()).is_error()) {
ph_load_result = EFAULT; ph_load_result = EFAULT;
return IterationDecision::Break; return IterationDecision::Break;
} }
@ -382,7 +385,7 @@ static KResultOr<LoadResult> load_elf_object(NonnullOwnPtr<Memory::AddressSpace>
// Accessing it would definitely be a bug. // Accessing it would definitely be a bug.
auto page_offset = program_header.vaddr(); auto page_offset = program_header.vaddr();
page_offset.mask(~PAGE_MASK); page_offset.mask(~PAGE_MASK);
if (!copy_to_user((u8*)region_or_error.value()->vaddr().as_ptr() + page_offset.get(), program_header.raw_data(), program_header.size_in_image())) { if (copy_to_user((u8*)region_or_error.value()->vaddr().as_ptr() + page_offset.get(), program_header.raw_data(), program_header.size_in_image()).is_error()) {
ph_load_result = EFAULT; ph_load_result = EFAULT;
return IterationDecision::Break; return IterationDecision::Break;
} }
@ -937,8 +940,7 @@ KResultOr<FlatPtr> Process::sys$execve(Userspace<const Syscall::SC_execve_params
// NOTE: Be extremely careful with allocating any kernel memory in exec(). // NOTE: Be extremely careful with allocating any kernel memory in exec().
// On success, the kernel stack will be lost. // On success, the kernel stack will be lost.
Syscall::SC_execve_params params; Syscall::SC_execve_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (params.arguments.length > ARG_MAX || params.environment.length > ARG_MAX) if (params.arguments.length > ARG_MAX || params.environment.length > ARG_MAX)
return E2BIG; return E2BIG;
@ -961,7 +963,7 @@ KResultOr<FlatPtr> Process::sys$execve(Userspace<const Syscall::SC_execve_params
Vector<Syscall::StringArgument, 32> strings; Vector<Syscall::StringArgument, 32> strings;
if (!strings.try_resize(list.length)) if (!strings.try_resize(list.length))
return false; return false;
if (!copy_from_user(strings.data(), list.strings, size.value())) if (copy_from_user(strings.data(), list.strings, size.value()).is_error())
return false; return false;
for (size_t i = 0; i < list.length; ++i) { for (size_t i = 0; i < list.length; ++i) {
auto string_or_error = try_copy_kstring_from_user(strings[i]); auto string_or_error = try_copy_kstring_from_user(strings[i]);

View file

@ -14,8 +14,7 @@ KResultOr<FlatPtr> Process::sys$ftruncate(int fd, Userspace<off_t*> userspace_le
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
off_t length; off_t length;
if (!copy_from_user(&length, userspace_length)) TRY(copy_from_user(&length, userspace_length));
return EFAULT;
if (length < 0) if (length < 0)
return EINVAL; return EINVAL;
auto description = fds().file_description(fd); auto description = fds().file_description(fd);

View file

@ -26,8 +26,7 @@ KResultOr<FlatPtr> Process::sys$futex(Userspace<const Syscall::SC_futex_params*>
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
Syscall::SC_futex_params params; Syscall::SC_futex_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
Thread::BlockTimeout timeout; Thread::BlockTimeout timeout;
u32 cmd = params.futex_op & FUTEX_CMD_MASK; u32 cmd = params.futex_op & FUTEX_CMD_MASK;

View file

@ -21,11 +21,8 @@ KResultOr<FlatPtr> Process::sys$get_stack_bounds(Userspace<FlatPtr*> user_stack_
FlatPtr stack_base = stack_region->range().base().get(); FlatPtr stack_base = stack_region->range().base().get();
size_t stack_size = stack_region->size(); size_t stack_size = stack_region->size();
if (!copy_to_user(user_stack_base, &stack_base)) TRY(copy_to_user(user_stack_base, &stack_base));
return EFAULT; return copy_to_user(user_stack_size, &stack_size);
if (!copy_to_user(user_stack_size, &stack_size))
return EFAULT;
return 0;
} }
} }

View file

@ -40,18 +40,20 @@ KResultOr<FlatPtr> Process::sys$getresuid(Userspace<UserID*> ruid, Userspace<Use
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
if (!copy_to_user(ruid, &m_protected_values.uid) || !copy_to_user(euid, &m_protected_values.euid) || !copy_to_user(suid, &m_protected_values.suid)) TRY(copy_to_user(ruid, &m_protected_values.uid));
return EFAULT; TRY(copy_to_user(euid, &m_protected_values.euid));
return 0; TRY(copy_to_user(suid, &m_protected_values.suid));
return KSuccess;
} }
KResultOr<FlatPtr> Process::sys$getresgid(Userspace<GroupID*> rgid, Userspace<GroupID*> egid, Userspace<GroupID*> sgid) KResultOr<FlatPtr> Process::sys$getresgid(Userspace<GroupID*> rgid, Userspace<GroupID*> egid, Userspace<GroupID*> sgid)
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
if (!copy_to_user(rgid, &m_protected_values.gid) || !copy_to_user(egid, &m_protected_values.egid) || !copy_to_user(sgid, &m_protected_values.sgid)) TRY(copy_to_user(rgid, &m_protected_values.gid));
return EFAULT; TRY(copy_to_user(egid, &m_protected_values.egid));
return 0; TRY(copy_to_user(sgid, &m_protected_values.sgid));
return KSuccess;
} }
KResultOr<FlatPtr> Process::sys$getgroups(size_t count, Userspace<gid_t*> user_gids) KResultOr<FlatPtr> Process::sys$getgroups(size_t count, Userspace<gid_t*> user_gids)
@ -62,11 +64,7 @@ KResultOr<FlatPtr> Process::sys$getgroups(size_t count, Userspace<gid_t*> user_g
return extra_gids().size(); return extra_gids().size();
if (count != extra_gids().size()) if (count != extra_gids().size())
return EINVAL; return EINVAL;
return copy_to_user(user_gids, extra_gids().data(), sizeof(gid_t) * count);
if (!copy_to_user(user_gids, extra_gids().data(), sizeof(gid_t) * count))
return EFAULT;
return 0;
} }
} }

View file

@ -17,8 +17,7 @@ KResultOr<FlatPtr> Process::sys$gethostname(Userspace<char*> buffer, size_t size
return hostname().with_shared([&](const auto& name) -> KResultOr<FlatPtr> { return hostname().with_shared([&](const auto& name) -> KResultOr<FlatPtr> {
if (size < (name.length() + 1)) if (size < (name.length() + 1))
return ENAMETOOLONG; return ENAMETOOLONG;
if (!copy_to_user(buffer, name.characters(), name.length() + 1)) TRY(copy_to_user(buffer, name.characters(), name.length() + 1));
return EFAULT;
return 0; return 0;
}); });
} }

View file

@ -48,8 +48,7 @@ KResultOr<FlatPtr> Process::sys$inode_watcher_add_watch(Userspace<const Syscall:
REQUIRE_PROMISE(rpath); REQUIRE_PROMISE(rpath);
Syscall::SC_inode_watcher_add_watch_params params; Syscall::SC_inode_watcher_add_watch_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto description = fds().file_description(params.fd); auto description = fds().file_description(params.fd);
if (!description) if (!description)

View file

@ -20,21 +20,15 @@ KResultOr<FlatPtr> Process::sys$setkeymap(Userspace<const Syscall::SC_setkeymap_
return EPERM; return EPERM;
Syscall::SC_setkeymap_params params; Syscall::SC_setkeymap_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
Keyboard::CharacterMapData character_map_data; Keyboard::CharacterMapData character_map_data;
if (!copy_n_from_user(character_map_data.map, params.map, CHAR_MAP_SIZE)) TRY(copy_n_from_user(character_map_data.map, params.map, CHAR_MAP_SIZE));
return EFAULT; TRY(copy_n_from_user(character_map_data.shift_map, params.shift_map, CHAR_MAP_SIZE));
if (!copy_n_from_user(character_map_data.shift_map, params.shift_map, CHAR_MAP_SIZE)) TRY(copy_n_from_user(character_map_data.alt_map, params.alt_map, CHAR_MAP_SIZE));
return EFAULT; TRY(copy_n_from_user(character_map_data.altgr_map, params.altgr_map, CHAR_MAP_SIZE));
if (!copy_n_from_user(character_map_data.alt_map, params.alt_map, CHAR_MAP_SIZE)) TRY(copy_n_from_user(character_map_data.shift_altgr_map, params.shift_altgr_map, CHAR_MAP_SIZE));
return EFAULT;
if (!copy_n_from_user(character_map_data.altgr_map, params.altgr_map, CHAR_MAP_SIZE))
return EFAULT;
if (!copy_n_from_user(character_map_data.shift_altgr_map, params.shift_altgr_map, CHAR_MAP_SIZE))
return EFAULT;
auto map_name = get_syscall_path_argument(params.map_name); auto map_name = get_syscall_path_argument(params.map_name);
if (map_name.is_error()) if (map_name.is_error())
@ -51,30 +45,22 @@ KResultOr<FlatPtr> Process::sys$getkeymap(Userspace<const Syscall::SC_getkeymap_
VERIFY_NO_PROCESS_BIG_LOCK(this); VERIFY_NO_PROCESS_BIG_LOCK(this);
REQUIRE_PROMISE(getkeymap); REQUIRE_PROMISE(getkeymap);
Syscall::SC_getkeymap_params params; Syscall::SC_getkeymap_params params {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
String keymap_name = HIDManagement::the().keymap_name(); String keymap_name = HIDManagement::the().keymap_name();
const Keyboard::CharacterMapData& character_maps = HIDManagement::the().character_maps(); const Keyboard::CharacterMapData& character_maps = HIDManagement::the().character_maps();
if (!copy_to_user(params.map, character_maps.map, CHAR_MAP_SIZE * sizeof(u32))) TRY(copy_to_user(params.map, character_maps.map, CHAR_MAP_SIZE * sizeof(u32)));
return EFAULT; TRY(copy_to_user(params.shift_map, character_maps.shift_map, CHAR_MAP_SIZE * sizeof(u32)));
if (!copy_to_user(params.shift_map, character_maps.shift_map, CHAR_MAP_SIZE * sizeof(u32))) TRY(copy_to_user(params.alt_map, character_maps.alt_map, CHAR_MAP_SIZE * sizeof(u32)));
return EFAULT; TRY(copy_to_user(params.altgr_map, character_maps.altgr_map, CHAR_MAP_SIZE * sizeof(u32)));
if (!copy_to_user(params.alt_map, character_maps.alt_map, CHAR_MAP_SIZE * sizeof(u32))) TRY(copy_to_user(params.shift_altgr_map, character_maps.shift_altgr_map, CHAR_MAP_SIZE * sizeof(u32)));
return EFAULT;
if (!copy_to_user(params.altgr_map, character_maps.altgr_map, CHAR_MAP_SIZE * sizeof(u32)))
return EFAULT;
if (!copy_to_user(params.shift_altgr_map, character_maps.shift_altgr_map, CHAR_MAP_SIZE * sizeof(u32)))
return EFAULT;
if (params.map_name.size < keymap_name.length()) if (params.map_name.size < keymap_name.length())
return ENAMETOOLONG; return ENAMETOOLONG;
if (!copy_to_user(params.map_name.data, keymap_name.characters(), keymap_name.length())) TRY(copy_to_user(params.map_name.data, keymap_name.characters(), keymap_name.length()));
return EFAULT; return KSuccess;
return 0;
} }
} }

View file

@ -15,8 +15,7 @@ KResultOr<FlatPtr> Process::sys$link(Userspace<const Syscall::SC_link_params*> u
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(cpath); REQUIRE_PROMISE(cpath);
Syscall::SC_link_params params; Syscall::SC_link_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto old_path = TRY(try_copy_kstring_from_user(params.old_path)); auto old_path = TRY(try_copy_kstring_from_user(params.old_path));
auto new_path = TRY(try_copy_kstring_from_user(params.new_path)); auto new_path = TRY(try_copy_kstring_from_user(params.new_path));
return VirtualFileSystem::the().link(old_path->view(), new_path->view(), current_directory()); return VirtualFileSystem::the().link(old_path->view(), new_path->view(), current_directory());
@ -27,8 +26,7 @@ KResultOr<FlatPtr> Process::sys$symlink(Userspace<const Syscall::SC_symlink_para
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(cpath); REQUIRE_PROMISE(cpath);
Syscall::SC_symlink_params params; Syscall::SC_symlink_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto target = TRY(get_syscall_path_argument(params.target)); auto target = TRY(get_syscall_path_argument(params.target));
auto linkpath = TRY(get_syscall_path_argument(params.linkpath)); auto linkpath = TRY(get_syscall_path_argument(params.linkpath));
return VirtualFileSystem::the().symlink(target->view(), linkpath->view(), current_directory()); return VirtualFileSystem::the().symlink(target->view(), linkpath->view(), current_directory());

View file

@ -17,12 +17,9 @@ KResultOr<FlatPtr> Process::sys$lseek(int fd, Userspace<off_t*> userspace_offset
if (!description) if (!description)
return EBADF; return EBADF;
off_t offset; off_t offset;
if (!copy_from_user(&offset, userspace_offset)) TRY(copy_from_user(&offset, userspace_offset));
return EFAULT;
auto seek_result = TRY(description->seek(offset, whence)); auto seek_result = TRY(description->seek(offset, whence));
if (!copy_to_user(userspace_offset, &seek_result)) return copy_to_user(userspace_offset, &seek_result);
return EFAULT;
return KSuccess;
} }
} }

View file

@ -15,8 +15,7 @@ KResultOr<FlatPtr> Process::sys$mknod(Userspace<const Syscall::SC_mknod_params*>
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(dpath); REQUIRE_PROMISE(dpath);
Syscall::SC_mknod_params params; Syscall::SC_mknod_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (!is_superuser() && !is_regular_file(params.mode) && !is_fifo(params.mode) && !is_socket(params.mode)) if (!is_superuser() && !is_regular_file(params.mode) && !is_fifo(params.mode) && !is_socket(params.mode))
return EPERM; return EPERM;
auto path = TRY(get_syscall_path_argument(params.path)); auto path = TRY(get_syscall_path_argument(params.path));

View file

@ -130,8 +130,7 @@ KResultOr<FlatPtr> Process::sys$mmap(Userspace<const Syscall::SC_mmap_params*> u
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
Syscall::SC_mmap_params params; Syscall::SC_mmap_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
FlatPtr addr = params.addr; FlatPtr addr = params.addr;
auto size = params.size; auto size = params.size;
@ -470,8 +469,7 @@ KResultOr<FlatPtr> Process::sys$set_mmap_name(Userspace<const Syscall::SC_set_mm
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
Syscall::SC_set_mmap_name_params params; Syscall::SC_set_mmap_name_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (params.name.length > PATH_MAX) if (params.name.length > PATH_MAX)
return ENAMETOOLONG; return ENAMETOOLONG;
@ -508,8 +506,7 @@ KResultOr<FlatPtr> Process::sys$mremap(Userspace<const Syscall::SC_mremap_params
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
Syscall::SC_mremap_params params {}; Syscall::SC_mremap_params params {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto old_range = TRY(expand_range_to_page_boundaries((FlatPtr)params.old_address, params.old_size)); auto old_range = TRY(expand_range_to_page_boundaries((FlatPtr)params.old_address, params.old_size));

View file

@ -27,8 +27,7 @@ KResultOr<FlatPtr> Process::sys$mount(Userspace<const Syscall::SC_mount_params*>
REQUIRE_NO_PROMISES; REQUIRE_NO_PROMISES;
Syscall::SC_mount_params params; Syscall::SC_mount_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto source_fd = params.source_fd; auto source_fd = params.source_fd;
auto target_or_error = try_copy_kstring_from_user(params.target); auto target_or_error = try_copy_kstring_from_user(params.target);

View file

@ -15,8 +15,7 @@ KResultOr<FlatPtr> Process::sys$open(Userspace<const Syscall::SC_open_params*> u
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_open_params params; Syscall::SC_open_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
int dirfd = params.dirfd; int dirfd = params.dirfd;
int options = params.options; int options = params.options;

View file

@ -36,12 +36,9 @@ KResultOr<FlatPtr> Process::sys$pipe(int pipefd[2], int flags)
m_fds[reader_fd_allocation.fd].set(move(reader_description), fd_flags); m_fds[reader_fd_allocation.fd].set(move(reader_description), fd_flags);
m_fds[writer_fd_allocation.fd].set(move(writer_description), fd_flags); m_fds[writer_fd_allocation.fd].set(move(writer_description), fd_flags);
if (!copy_to_user(&pipefd[0], &reader_fd_allocation.fd)) TRY(copy_to_user(&pipefd[0], &reader_fd_allocation.fd));
return EFAULT; TRY(copy_to_user(&pipefd[1], &writer_fd_allocation.fd));
if (!copy_to_user(&pipefd[1], &writer_fd_allocation.fd)) return KSuccess;
return EFAULT;
return 0;
} }
} }

View file

@ -13,8 +13,7 @@ KResultOr<FlatPtr> Process::sys$pledge(Userspace<const Syscall::SC_pledge_params
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_pledge_params params; Syscall::SC_pledge_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (params.promises.length > 1024 || params.execpromises.length > 1024) if (params.promises.length > 1024 || params.execpromises.length > 1024)
return E2BIG; return E2BIG;

View file

@ -30,9 +30,7 @@ KResultOr<FlatPtr> Process::sys$get_process_name(Userspace<char*> buffer, size_t
if (m_name.length() + 1 > buffer_size) if (m_name.length() + 1 > buffer_size)
return ENAMETOOLONG; return ENAMETOOLONG;
if (!copy_to_user(buffer, m_name.characters(), m_name.length() + 1)) return copy_to_user(buffer, m_name.characters(), m_name.length() + 1);
return EFAULT;
return 0;
} }
KResultOr<FlatPtr> Process::sys$set_process_name(Userspace<const char*> user_name, size_t user_name_length) KResultOr<FlatPtr> Process::sys$set_process_name(Userspace<const char*> user_name, size_t user_name_length)
@ -56,8 +54,7 @@ KResultOr<FlatPtr> Process::sys$set_coredump_metadata(Userspace<const Syscall::S
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_set_coredump_metadata_params params; Syscall::SC_set_coredump_metadata_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (params.key.length == 0 || params.key.length > 16 * KiB) if (params.key.length == 0 || params.key.length > 16 * KiB)
return EINVAL; return EINVAL;
if (params.value.length > 16 * KiB) if (params.value.length > 16 * KiB)

View file

@ -92,8 +92,7 @@ static KResultOr<u32> handle_ptrace(const Kernel::Syscall::SC_ptrace_params& par
if (!tracer->has_regs()) if (!tracer->has_regs())
return EINVAL; return EINVAL;
auto* regs = reinterpret_cast<PtraceRegisters*>(params.addr); auto* regs = reinterpret_cast<PtraceRegisters*>(params.addr);
if (!copy_to_user(regs, &tracer->regs())) TRY(copy_to_user(regs, &tracer->regs()));
return EFAULT;
break; break;
} }
@ -102,8 +101,7 @@ static KResultOr<u32> handle_ptrace(const Kernel::Syscall::SC_ptrace_params& par
return EINVAL; return EINVAL;
PtraceRegisters regs {}; PtraceRegisters regs {};
if (!copy_from_user(&regs, (const PtraceRegisters*)params.addr)) TRY(copy_from_user(&regs, (const PtraceRegisters*)params.addr));
return EFAULT;
auto& peer_saved_registers = peer->get_register_dump_from_stack(); auto& peer_saved_registers = peer->get_register_dump_from_stack();
// Verify that the saved registers are in usermode context // Verify that the saved registers are in usermode context
@ -117,13 +115,11 @@ static KResultOr<u32> handle_ptrace(const Kernel::Syscall::SC_ptrace_params& par
case PT_PEEK: { case PT_PEEK: {
Kernel::Syscall::SC_ptrace_peek_params peek_params {}; Kernel::Syscall::SC_ptrace_peek_params peek_params {};
if (!copy_from_user(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr))) TRY(copy_from_user(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr)));
return EFAULT;
if (!Memory::is_user_address(VirtualAddress { peek_params.address })) if (!Memory::is_user_address(VirtualAddress { peek_params.address }))
return EFAULT; return EFAULT;
auto data = TRY(peer->process().peek_user_data(Userspace<const u32*> { (FlatPtr)peek_params.address })); auto data = TRY(peer->process().peek_user_data(Userspace<const u32*> { (FlatPtr)peek_params.address }));
if (!copy_to_user(peek_params.out_data, &data)) TRY(copy_to_user(peek_params.out_data, &data));
return EFAULT;
break; break;
} }
@ -134,11 +130,9 @@ static KResultOr<u32> handle_ptrace(const Kernel::Syscall::SC_ptrace_params& par
case PT_PEEKDEBUG: { case PT_PEEKDEBUG: {
Kernel::Syscall::SC_ptrace_peek_params peek_params {}; Kernel::Syscall::SC_ptrace_peek_params peek_params {};
if (!copy_from_user(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr))) TRY(copy_from_user(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr)));
return EFAULT;
auto data = TRY(peer->peek_debug_register(reinterpret_cast<uintptr_t>(peek_params.address))); auto data = TRY(peer->peek_debug_register(reinterpret_cast<uintptr_t>(peek_params.address)));
if (!copy_to_user(peek_params.out_data, &data)) TRY(copy_to_user(peek_params.out_data, &data));
return EFAULT;
break; break;
} }
case PT_POKEDEBUG: case PT_POKEDEBUG:
@ -155,8 +149,7 @@ KResultOr<FlatPtr> Process::sys$ptrace(Userspace<const Syscall::SC_ptrace_params
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(ptrace); REQUIRE_PROMISE(ptrace);
Syscall::SC_ptrace_params params {}; Syscall::SC_ptrace_params params {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto result = handle_ptrace(params, *this); auto result = handle_ptrace(params, *this);
return result.is_error() ? result.error().error() : result.value(); return result.is_error() ? result.error().error() : result.value();
} }
@ -173,17 +166,12 @@ bool Process::has_tracee_thread(ProcessID tracer_pid)
KResultOr<u32> Process::peek_user_data(Userspace<const u32*> address) KResultOr<u32> Process::peek_user_data(Userspace<const u32*> address)
{ {
uint32_t result;
// This function can be called from the context of another // This function can be called from the context of another
// process that called PT_PEEK // process that called PT_PEEK
ProcessPagingScope scope(*this); ProcessPagingScope scope(*this);
if (!copy_from_user(&result, address)) { uint32_t data;
dbgln("Invalid address for peek_user_data: {}", address.ptr()); TRY(copy_from_user(&data, address));
return EFAULT; return data;
}
return result;
} }
KResult Process::poke_user_data(Userspace<u32*> address, u32 data) KResult Process::poke_user_data(Userspace<u32*> address, u32 data)
@ -215,12 +203,7 @@ KResult Process::poke_user_data(Userspace<u32*> address, u32 data)
} }
}); });
if (!copy_to_user(address, &data)) { return copy_to_user(address, &data);
dbgln("poke_user_data: Bad address {:p}", address.ptr());
return EFAULT;
}
return KSuccess;
} }
KResultOr<u32> Thread::peek_debug_register(u32 register_index) KResultOr<u32> Thread::peek_debug_register(u32 register_index)

View file

@ -27,8 +27,7 @@ KResultOr<FlatPtr> Process::sys$readv(int fd, Userspace<const struct iovec*> iov
Vector<iovec, 32> vecs; Vector<iovec, 32> vecs;
if (!vecs.try_resize(iov_count)) if (!vecs.try_resize(iov_count))
return ENOMEM; return ENOMEM;
if (!copy_n_from_user(vecs.data(), iov, iov_count)) TRY(copy_n_from_user(vecs.data(), iov, iov_count));
return EFAULT;
for (auto& vec : vecs) { for (auto& vec : vecs) {
total_length += vec.iov_len; total_length += vec.iov_len;
if (total_length > NumericLimits<i32>::max()) if (total_length > NumericLimits<i32>::max())

View file

@ -16,8 +16,7 @@ KResultOr<FlatPtr> Process::sys$readlink(Userspace<const Syscall::SC_readlink_pa
REQUIRE_PROMISE(rpath); REQUIRE_PROMISE(rpath);
Syscall::SC_readlink_params params; Syscall::SC_readlink_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto path = get_syscall_path_argument(params.path); auto path = get_syscall_path_argument(params.path);
if (path.is_error()) if (path.is_error())
@ -37,8 +36,7 @@ KResultOr<FlatPtr> Process::sys$readlink(Userspace<const Syscall::SC_readlink_pa
auto& link_target = *contents.value(); auto& link_target = *contents.value();
auto size_to_copy = min(link_target.size(), params.buffer.size); auto size_to_copy = min(link_target.size(), params.buffer.size);
if (!copy_to_user(params.buffer.data, link_target.data(), size_to_copy)) TRY(copy_to_user(params.buffer.data, link_target.data(), size_to_copy));
return EFAULT;
// Note: we return the whole size here, not the copied size. // Note: we return the whole size here, not the copied size.
return link_target.size(); return link_target.size();
} }

View file

@ -17,8 +17,7 @@ KResultOr<FlatPtr> Process::sys$realpath(Userspace<const Syscall::SC_realpath_pa
REQUIRE_PROMISE(rpath); REQUIRE_PROMISE(rpath);
Syscall::SC_realpath_params params; Syscall::SC_realpath_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto path = get_syscall_path_argument(params.path); auto path = get_syscall_path_argument(params.path);
if (path.is_error()) if (path.is_error())
@ -34,8 +33,7 @@ KResultOr<FlatPtr> Process::sys$realpath(Userspace<const Syscall::SC_realpath_pa
size_t ideal_size = absolute_path->length() + 1; size_t ideal_size = absolute_path->length() + 1;
auto size_to_copy = min(ideal_size, params.buffer.size); auto size_to_copy = min(ideal_size, params.buffer.size);
if (!copy_to_user(params.buffer.data, absolute_path->characters(), size_to_copy)) TRY(copy_to_user(params.buffer.data, absolute_path->characters(), size_to_copy));
return EFAULT;
// Note: we return the whole size here, not the copied size. // Note: we return the whole size here, not the copied size.
return ideal_size; return ideal_size;
}; };

View file

@ -15,8 +15,7 @@ KResultOr<FlatPtr> Process::sys$rename(Userspace<const Syscall::SC_rename_params
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(cpath); REQUIRE_PROMISE(cpath);
Syscall::SC_rename_params params; Syscall::SC_rename_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto old_path = get_syscall_path_argument(params.old_path); auto old_path = get_syscall_path_argument(params.old_path);
if (old_path.is_error()) if (old_path.is_error())
return old_path.error(); return old_path.error();

View file

@ -21,8 +21,7 @@ KResultOr<FlatPtr> Process::sys$sched_setparam(int pid, Userspace<const struct s
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(proc); REQUIRE_PROMISE(proc);
struct sched_param desired_param; struct sched_param desired_param;
if (!copy_from_user(&desired_param, user_param)) TRY(copy_from_user(&desired_param, user_param));
return EFAULT;
if (desired_param.sched_priority < THREAD_PRIORITY_MIN || desired_param.sched_priority > THREAD_PRIORITY_MAX) if (desired_param.sched_priority < THREAD_PRIORITY_MIN || desired_param.sched_priority > THREAD_PRIORITY_MAX)
return EINVAL; return EINVAL;
@ -68,9 +67,8 @@ KResultOr<FlatPtr> Process::sys$sched_getparam(pid_t pid, Userspace<struct sched
struct sched_param param { struct sched_param param {
priority priority
}; };
if (!copy_to_user(user_param, &param))
return EFAULT; return copy_to_user(user_param, &param);
return 0;
} }
} }

View file

@ -20,8 +20,7 @@ KResultOr<FlatPtr> Process::sys$select(Userspace<const Syscall::SC_select_params
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
Syscall::SC_select_params params {}; Syscall::SC_select_params params {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (params.nfds < 0) if (params.nfds < 0)
return EINVAL; return EINVAL;
@ -39,8 +38,7 @@ KResultOr<FlatPtr> Process::sys$select(Userspace<const Syscall::SC_select_params
u32 previous_signal_mask = 0; u32 previous_signal_mask = 0;
if (params.sigmask) { if (params.sigmask) {
sigset_t sigmask_copy; sigset_t sigmask_copy;
if (!copy_from_user(&sigmask_copy, params.sigmask)) TRY(copy_from_user(&sigmask_copy, params.sigmask));
return EFAULT;
previous_signal_mask = current_thread->update_signal_mask(sigmask_copy); previous_signal_mask = current_thread->update_signal_mask(sigmask_copy);
} }
ScopeGuard rollback_signal_mask([&]() { ScopeGuard rollback_signal_mask([&]() {
@ -54,12 +52,14 @@ KResultOr<FlatPtr> Process::sys$select(Userspace<const Syscall::SC_select_params
if (bytes_used > sizeof(fds_read)) if (bytes_used > sizeof(fds_read))
return EINVAL; return EINVAL;
if (params.readfds && !copy_from_user(&fds_read, params.readfds, bytes_used)) if (params.readfds)
return EFAULT; TRY(copy_from_user(&fds_read, params.readfds, bytes_used));
if (params.writefds && !copy_from_user(&fds_write, params.writefds, bytes_used))
return EFAULT; if (params.writefds)
if (params.exceptfds && !copy_from_user(&fds_except, params.exceptfds, bytes_used)) TRY(copy_from_user(&fds_write, params.writefds, bytes_used));
return EFAULT;
if (params.exceptfds)
TRY(copy_from_user(&fds_except, params.exceptfds, bytes_used));
Thread::SelectBlocker::FDVector fds_info; Thread::SelectBlocker::FDVector fds_info;
Vector<int, FD_SETSIZE> selected_fds; Vector<int, FD_SETSIZE> selected_fds;
@ -119,12 +119,12 @@ KResultOr<FlatPtr> Process::sys$select(Userspace<const Syscall::SC_select_params
} }
} }
if (params.readfds && !copy_to_user(params.readfds, &fds_read, bytes_used)) if (params.readfds)
return EFAULT; TRY(copy_to_user(params.readfds, &fds_read, bytes_used));
if (params.writefds && !copy_to_user(params.writefds, &fds_write, bytes_used)) if (params.writefds)
return EFAULT; TRY(copy_to_user(params.writefds, &fds_write, bytes_used));
if (params.exceptfds && !copy_to_user(params.exceptfds, &fds_except, bytes_used)) if (params.exceptfds)
return EFAULT; TRY(copy_to_user(params.exceptfds, &fds_except, bytes_used));
return marked_fd_count; return marked_fd_count;
} }
@ -133,9 +133,8 @@ KResultOr<FlatPtr> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> u
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
Syscall::SC_poll_params params; Syscall::SC_poll_params params {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (params.nfds >= fds().max_open()) if (params.nfds >= fds().max_open())
return ENOBUFS; return ENOBUFS;
@ -149,8 +148,8 @@ KResultOr<FlatPtr> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> u
} }
sigset_t sigmask = {}; sigset_t sigmask = {};
if (params.sigmask && !copy_from_user(&sigmask, params.sigmask)) if (params.sigmask)
return EFAULT; TRY(copy_from_user(&sigmask, params.sigmask));
Vector<pollfd, FD_SETSIZE> fds_copy; Vector<pollfd, FD_SETSIZE> fds_copy;
if (params.nfds > 0) { if (params.nfds > 0) {
@ -160,8 +159,7 @@ KResultOr<FlatPtr> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> u
return EFAULT; return EFAULT;
if (!fds_copy.try_resize(params.nfds)) if (!fds_copy.try_resize(params.nfds))
return ENOMEM; return ENOMEM;
if (!copy_from_user(fds_copy.data(), &params.fds[0], nfds_checked.value())) TRY(copy_from_user(fds_copy.data(), &params.fds[0], nfds_checked.value()));
return EFAULT;
} }
Thread::SelectBlocker::FDVector fds_info; Thread::SelectBlocker::FDVector fds_info;
@ -234,8 +232,8 @@ KResultOr<FlatPtr> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> u
fds_with_revents++; fds_with_revents++;
} }
if (params.nfds > 0 && !copy_to_user(&params.fds[0], fds_copy.data(), params.nfds * sizeof(pollfd))) if (params.nfds > 0)
return EFAULT; TRY(copy_to_user(&params.fds[0], fds_copy.data(), params.nfds * sizeof(pollfd)));
return fds_with_revents; return fds_with_revents;
} }

View file

@ -171,8 +171,7 @@ KResultOr<FlatPtr> Process::sys$setgroups(size_t count, Userspace<const gid_t*>
Vector<gid_t> new_extra_gids; Vector<gid_t> new_extra_gids;
if (!new_extra_gids.try_resize(count)) if (!new_extra_gids.try_resize(count))
return ENOMEM; return ENOMEM;
if (!copy_n_from_user(new_extra_gids.data(), user_gids, count)) TRY(copy_n_from_user(new_extra_gids.data(), user_gids, count));
return EFAULT;
HashTable<gid_t> unique_extra_gids; HashTable<gid_t> unique_extra_gids;
for (auto& extra_gid : new_extra_gids) { for (auto& extra_gid : new_extra_gids) {

View file

@ -18,8 +18,7 @@ KResultOr<FlatPtr> Process::sys$sigprocmask(int how, Userspace<const sigset_t*>
u32 previous_signal_mask; u32 previous_signal_mask;
if (set) { if (set) {
sigset_t set_value; sigset_t set_value;
if (!copy_from_user(&set_value, set)) TRY(copy_from_user(&set_value, set));
return EFAULT;
switch (how) { switch (how) {
case SIG_BLOCK: case SIG_BLOCK:
previous_signal_mask = current_thread->signal_mask_block(set_value, true); previous_signal_mask = current_thread->signal_mask_block(set_value, true);
@ -36,8 +35,9 @@ KResultOr<FlatPtr> Process::sys$sigprocmask(int how, Userspace<const sigset_t*>
} else { } else {
previous_signal_mask = current_thread->signal_mask(); previous_signal_mask = current_thread->signal_mask();
} }
if (old_set && !copy_to_user(old_set, &previous_signal_mask)) if (old_set) {
return EFAULT; TRY(copy_to_user(old_set, &previous_signal_mask));
}
return 0; return 0;
} }
@ -46,9 +46,7 @@ KResultOr<FlatPtr> Process::sys$sigpending(Userspace<sigset_t*> set)
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
auto pending_signals = Thread::current()->pending_signals(); auto pending_signals = Thread::current()->pending_signals();
if (!copy_to_user(set, &pending_signals)) return copy_to_user(set, &pending_signals);
return EFAULT;
return 0;
} }
KResultOr<FlatPtr> Process::sys$sigaction(int signum, Userspace<const sigaction*> user_act, Userspace<sigaction*> user_old_act) KResultOr<FlatPtr> Process::sys$sigaction(int signum, Userspace<const sigaction*> user_act, Userspace<sigaction*> user_old_act)
@ -64,13 +62,11 @@ KResultOr<FlatPtr> Process::sys$sigaction(int signum, Userspace<const sigaction*
sigaction old_act {}; sigaction old_act {};
old_act.sa_flags = action.flags; old_act.sa_flags = action.flags;
old_act.sa_sigaction = reinterpret_cast<decltype(old_act.sa_sigaction)>(action.handler_or_sigaction.as_ptr()); old_act.sa_sigaction = reinterpret_cast<decltype(old_act.sa_sigaction)>(action.handler_or_sigaction.as_ptr());
if (!copy_to_user(user_old_act, &old_act)) TRY(copy_to_user(user_old_act, &old_act));
return EFAULT;
} }
if (user_act) { if (user_act) {
sigaction act {}; sigaction act {};
if (!copy_from_user(&act, user_act)) TRY(copy_from_user(&act, user_act));
return EFAULT;
action.flags = act.sa_flags; action.flags = act.sa_flags;
action.handler_or_sigaction = VirtualAddress { reinterpret_cast<void*>(act.sa_sigaction) }; action.handler_or_sigaction = VirtualAddress { reinterpret_cast<void*>(act.sa_sigaction) };
} }

View file

@ -80,9 +80,8 @@ KResultOr<FlatPtr> Process::sys$accept4(Userspace<const Syscall::SC_accept4_para
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(accept); REQUIRE_PROMISE(accept);
Syscall::SC_accept4_params params; Syscall::SC_accept4_params params = {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
int accepting_socket_fd = params.sockfd; int accepting_socket_fd = params.sockfd;
Userspace<sockaddr*> user_address((FlatPtr)params.addr); Userspace<sockaddr*> user_address((FlatPtr)params.addr);
@ -90,8 +89,9 @@ KResultOr<FlatPtr> Process::sys$accept4(Userspace<const Syscall::SC_accept4_para
int flags = params.flags; int flags = params.flags;
socklen_t address_size = 0; socklen_t address_size = 0;
if (user_address && !copy_from_user(&address_size, static_ptr_cast<const socklen_t*>(user_address_size))) if (user_address) {
return EFAULT; TRY(copy_from_user(&address_size, static_ptr_cast<const socklen_t*>(user_address_size)));
}
auto fd_allocation = TRY(m_fds.allocate()); auto fd_allocation = TRY(m_fds.allocate());
auto accepting_socket_description = fds().file_description(accepting_socket_fd); auto accepting_socket_description = fds().file_description(accepting_socket_fd);
@ -117,10 +117,8 @@ KResultOr<FlatPtr> Process::sys$accept4(Userspace<const Syscall::SC_accept4_para
sockaddr_un address_buffer; sockaddr_un address_buffer;
address_size = min(sizeof(sockaddr_un), static_cast<size_t>(address_size)); address_size = min(sizeof(sockaddr_un), static_cast<size_t>(address_size));
accepted_socket->get_peer_address((sockaddr*)&address_buffer, &address_size); accepted_socket->get_peer_address((sockaddr*)&address_buffer, &address_size);
if (!copy_to_user(user_address, &address_buffer, address_size)) TRY(copy_to_user(user_address, &address_buffer, address_size));
return EFAULT; TRY(copy_to_user(user_address_size, &address_size));
if (!copy_to_user(user_address_size, &address_size))
return EFAULT;
} }
auto accepted_socket_description = TRY(FileDescription::try_create(*accepted_socket)); auto accepted_socket_description = TRY(FileDescription::try_create(*accepted_socket));
@ -175,17 +173,15 @@ KResultOr<FlatPtr> Process::sys$sendmsg(int sockfd, Userspace<const struct msghd
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
struct msghdr msg; struct msghdr msg = {};
if (!copy_from_user(&msg, user_msg)) TRY(copy_from_user(&msg, user_msg));
return EFAULT;
if (msg.msg_iovlen != 1) if (msg.msg_iovlen != 1)
return ENOTSUP; // FIXME: Support this :) return ENOTSUP; // FIXME: Support this :)
Vector<iovec, 1> iovs; Vector<iovec, 1> iovs;
if (!iovs.try_resize(msg.msg_iovlen)) if (!iovs.try_resize(msg.msg_iovlen))
return ENOMEM; return ENOMEM;
if (!copy_n_from_user(iovs.data(), msg.msg_iov, msg.msg_iovlen)) TRY(copy_n_from_user(iovs.data(), msg.msg_iov, msg.msg_iovlen));
return EFAULT;
if (iovs[0].iov_len > NumericLimits<ssize_t>::max()) if (iovs[0].iov_len > NumericLimits<ssize_t>::max())
return EINVAL; return EINVAL;
@ -216,16 +212,14 @@ KResultOr<FlatPtr> Process::sys$recvmsg(int sockfd, Userspace<struct msghdr*> us
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
struct msghdr msg; struct msghdr msg;
if (!copy_from_user(&msg, user_msg)) TRY(copy_from_user(&msg, user_msg));
return EFAULT;
if (msg.msg_iovlen != 1) if (msg.msg_iovlen != 1)
return ENOTSUP; // FIXME: Support this :) return ENOTSUP; // FIXME: Support this :)
Vector<iovec, 1> iovs; Vector<iovec, 1> iovs;
if (!iovs.try_resize(msg.msg_iovlen)) if (!iovs.try_resize(msg.msg_iovlen))
return ENOMEM; return ENOMEM;
if (!copy_n_from_user(iovs.data(), msg.msg_iov, msg.msg_iovlen)) TRY(copy_n_from_user(iovs.data(), msg.msg_iov, msg.msg_iovlen));
return EFAULT;
Userspace<sockaddr*> user_addr((FlatPtr)msg.msg_name); Userspace<sockaddr*> user_addr((FlatPtr)msg.msg_name);
Userspace<socklen_t*> user_addr_length(msg.msg_name ? (FlatPtr)&user_msg.unsafe_userspace_ptr()->msg_namelen : 0); Userspace<socklen_t*> user_addr_length(msg.msg_name ? (FlatPtr)&user_msg.unsafe_userspace_ptr()->msg_namelen : 0);
@ -272,25 +266,20 @@ KResultOr<FlatPtr> Process::sys$recvmsg(int sockfd, Userspace<struct msghdr*> us
msg_flags |= MSG_CTRUNC; msg_flags |= MSG_CTRUNC;
} else { } else {
cmsg_timestamp = { { control_length, SOL_SOCKET, SCM_TIMESTAMP }, timestamp.to_timeval() }; cmsg_timestamp = { { control_length, SOL_SOCKET, SCM_TIMESTAMP }, timestamp.to_timeval() };
if (!copy_to_user(msg.msg_control, &cmsg_timestamp, control_length)) TRY(copy_to_user(msg.msg_control, &cmsg_timestamp, control_length));
return EFAULT;
} }
if (!copy_to_user(&user_msg.unsafe_userspace_ptr()->msg_controllen, &control_length)) TRY(copy_to_user(&user_msg.unsafe_userspace_ptr()->msg_controllen, &control_length));
return EFAULT;
} }
if (!copy_to_user(&user_msg.unsafe_userspace_ptr()->msg_flags, &msg_flags)) TRY(copy_to_user(&user_msg.unsafe_userspace_ptr()->msg_flags, &msg_flags));
return EFAULT;
return result.value(); return result.value();
} }
template<bool sockname, typename Params> template<bool sockname, typename Params>
int Process::get_sock_or_peer_name(const Params& params) KResult Process::get_sock_or_peer_name(const Params& params)
{ {
socklen_t addrlen_value; socklen_t addrlen_value;
if (!copy_from_user(&addrlen_value, params.addrlen, sizeof(socklen_t))) TRY(copy_from_user(&addrlen_value, params.addrlen, sizeof(socklen_t)));
return EFAULT;
if (addrlen_value <= 0) if (addrlen_value <= 0)
return EINVAL; return EINVAL;
@ -311,37 +300,31 @@ int Process::get_sock_or_peer_name(const Params& params)
socket.get_local_address((sockaddr*)&address_buffer, &addrlen_value); socket.get_local_address((sockaddr*)&address_buffer, &addrlen_value);
else else
socket.get_peer_address((sockaddr*)&address_buffer, &addrlen_value); socket.get_peer_address((sockaddr*)&address_buffer, &addrlen_value);
if (!copy_to_user(params.addr, &address_buffer, addrlen_value)) TRY(copy_to_user(params.addr, &address_buffer, addrlen_value));
return EFAULT; return copy_to_user(params.addrlen, &addrlen_value);
if (!copy_to_user(params.addrlen, &addrlen_value))
return EFAULT;
return 0;
} }
KResultOr<FlatPtr> Process::sys$getsockname(Userspace<const Syscall::SC_getsockname_params*> user_params) KResultOr<FlatPtr> Process::sys$getsockname(Userspace<const Syscall::SC_getsockname_params*> user_params)
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_getsockname_params params; Syscall::SC_getsockname_params params = {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
return get_sock_or_peer_name<true>(params); return get_sock_or_peer_name<true>(params);
} }
KResultOr<FlatPtr> Process::sys$getpeername(Userspace<const Syscall::SC_getpeername_params*> user_params) KResultOr<FlatPtr> Process::sys$getpeername(Userspace<const Syscall::SC_getpeername_params*> user_params)
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_getpeername_params params; Syscall::SC_getpeername_params params = {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
return get_sock_or_peer_name<false>(params); return get_sock_or_peer_name<false>(params);
} }
KResultOr<FlatPtr> Process::sys$getsockopt(Userspace<const Syscall::SC_getsockopt_params*> user_params) KResultOr<FlatPtr> Process::sys$getsockopt(Userspace<const Syscall::SC_getsockopt_params*> user_params)
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_getsockopt_params params; Syscall::SC_getsockopt_params params = {};
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
int sockfd = params.sockfd; int sockfd = params.sockfd;
int level = params.level; int level = params.level;
@ -350,8 +333,7 @@ KResultOr<FlatPtr> Process::sys$getsockopt(Userspace<const Syscall::SC_getsockop
Userspace<socklen_t*> user_value_size((FlatPtr)params.value_size); Userspace<socklen_t*> user_value_size((FlatPtr)params.value_size);
socklen_t value_size; socklen_t value_size;
if (!copy_from_user(&value_size, params.value_size, sizeof(socklen_t))) TRY(copy_from_user(&value_size, params.value_size, sizeof(socklen_t)));
return EFAULT;
auto description = fds().file_description(sockfd); auto description = fds().file_description(sockfd);
if (!description) if (!description)
@ -368,8 +350,7 @@ KResultOr<FlatPtr> Process::sys$setsockopt(Userspace<const Syscall::SC_setsockop
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_setsockopt_params params; Syscall::SC_setsockopt_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
Userspace<const void*> user_value((FlatPtr)params.value); Userspace<const void*> user_value((FlatPtr)params.value);
auto description = fds().file_description(params.sockfd); auto description = fds().file_description(params.sockfd);
if (!description) if (!description)
@ -385,8 +366,7 @@ KResultOr<FlatPtr> Process::sys$socketpair(Userspace<const Syscall::SC_socketpai
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_socketpair_params params; Syscall::SC_socketpair_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (params.domain != AF_LOCAL) if (params.domain != AF_LOCAL)
return EINVAL; return EINVAL;
@ -405,7 +385,7 @@ KResultOr<FlatPtr> Process::sys$socketpair(Userspace<const Syscall::SC_socketpai
setup_socket_fd(fds[0], pair.description0, params.type); setup_socket_fd(fds[0], pair.description0, params.type);
setup_socket_fd(fds[1], pair.description1, params.type); setup_socket_fd(fds[1], pair.description1, params.type);
if (!copy_to_user(params.sv, fds, sizeof(fds))) { if (copy_to_user(params.sv, fds, sizeof(fds)).is_error()) {
// Avoid leaking both file descriptors on error. // Avoid leaking both file descriptors on error.
m_fds[fds[0]] = {}; m_fds[fds[0]] = {};
m_fds[fds[1]] = {}; m_fds[fds[1]] = {};

View file

@ -19,10 +19,8 @@ KResultOr<FlatPtr> Process::sys$fstat(int fd, Userspace<stat*> user_statbuf)
if (!description) if (!description)
return EBADF; return EBADF;
stat buffer = {}; stat buffer = {};
auto result = description->stat(buffer); TRY(description->stat(buffer));
if (!copy_to_user(user_statbuf, &buffer)) return copy_to_user(user_statbuf, &buffer);
return EFAULT;
return result;
} }
KResultOr<FlatPtr> Process::sys$stat(Userspace<const Syscall::SC_stat_params*> user_params) KResultOr<FlatPtr> Process::sys$stat(Userspace<const Syscall::SC_stat_params*> user_params)
@ -30,8 +28,7 @@ KResultOr<FlatPtr> Process::sys$stat(Userspace<const Syscall::SC_stat_params*> u
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
REQUIRE_PROMISE(rpath); REQUIRE_PROMISE(rpath);
Syscall::SC_stat_params params; Syscall::SC_stat_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto path = get_syscall_path_argument(params.path); auto path = get_syscall_path_argument(params.path);
if (path.is_error()) if (path.is_error())
return path.error(); return path.error();
@ -55,9 +52,7 @@ KResultOr<FlatPtr> Process::sys$stat(Userspace<const Syscall::SC_stat_params*> u
auto result = metadata_or_error.value().stat(statbuf); auto result = metadata_or_error.value().stat(statbuf);
if (result.is_error()) if (result.is_error())
return result; return result;
if (!copy_to_user(params.statbuf, &statbuf)) return copy_to_user(params.statbuf, &statbuf);
return EFAULT;
return 0;
} }
} }

View file

@ -62,10 +62,7 @@ KResultOr<FlatPtr> Process::do_statvfs(String path, statvfs* buf)
} }
} }
if (!copy_to_user(buf, &kernelbuf)) return copy_to_user(buf, &kernelbuf);
return EFAULT;
return 0;
} }
KResultOr<FlatPtr> Process::sys$statvfs(Userspace<const Syscall::SC_statvfs_params*> user_params) KResultOr<FlatPtr> Process::sys$statvfs(Userspace<const Syscall::SC_statvfs_params*> user_params)
@ -74,8 +71,7 @@ KResultOr<FlatPtr> Process::sys$statvfs(Userspace<const Syscall::SC_statvfs_para
REQUIRE_PROMISE(rpath); REQUIRE_PROMISE(rpath);
Syscall::SC_statvfs_params params; Syscall::SC_statvfs_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
auto path = get_syscall_path_argument(params.path); auto path = get_syscall_path_argument(params.path);
if (path.is_error()) if (path.is_error())
return path.error(); return path.error();

View file

@ -19,8 +19,7 @@ KResultOr<FlatPtr> Process::sys$create_thread(void* (*entry)(void*), Userspace<c
REQUIRE_PROMISE(thread); REQUIRE_PROMISE(thread);
Syscall::SC_create_thread_params params; Syscall::SC_create_thread_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
unsigned detach_state = params.detach_state; unsigned detach_state = params.detach_state;
int schedule_priority = params.schedule_priority; int schedule_priority = params.schedule_priority;
@ -151,9 +150,10 @@ KResultOr<FlatPtr> Process::sys$join_thread(pid_t tid, Userspace<void**> exit_va
dbgln("join_thread: retrying"); dbgln("join_thread: retrying");
} }
if (exit_value && !copy_to_user(exit_value, &joinee_exit_value)) if (exit_value)
return EFAULT; TRY(copy_to_user(exit_value, &joinee_exit_value));
return 0;
return KSuccess;
} }
KResultOr<FlatPtr> Process::sys$kill_thread(pid_t tid, int signal) KResultOr<FlatPtr> Process::sys$kill_thread(pid_t tid, int signal)
@ -212,17 +212,14 @@ KResultOr<FlatPtr> Process::sys$get_thread_name(pid_t tid, Userspace<char*> buff
if (thread_name.is_null()) { if (thread_name.is_null()) {
char null_terminator = '\0'; char null_terminator = '\0';
if (!copy_to_user(buffer, &null_terminator, sizeof(null_terminator))) TRY(copy_to_user(buffer, &null_terminator, sizeof(null_terminator)));
return EFAULT; return KSuccess;
return 0;
} }
if (thread_name.length() + 1 > buffer_size) if (thread_name.length() + 1 > buffer_size)
return ENAMETOOLONG; return ENAMETOOLONG;
if (!copy_to_user(buffer, thread_name.characters_without_null_termination(), thread_name.length() + 1)) return copy_to_user(buffer, thread_name.characters_without_null_termination(), thread_name.length() + 1);
return EFAULT;
return 0;
} }
KResultOr<FlatPtr> Process::sys$gettid() KResultOr<FlatPtr> Process::sys$gettid()

View file

@ -18,9 +18,7 @@ KResultOr<FlatPtr> Process::sys$times(Userspace<tms*> user_times)
times.tms_cutime = m_ticks_in_user_for_dead_children; times.tms_cutime = m_ticks_in_user_for_dead_children;
times.tms_cstime = m_ticks_in_kernel_for_dead_children; times.tms_cstime = m_ticks_in_kernel_for_dead_children;
if (!copy_to_user(user_times, &times)) TRY(copy_to_user(user_times, &times));
return EFAULT;
return TimeManagement::the().uptime_ms() & 0x7fffffff; return TimeManagement::the().uptime_ms() & 0x7fffffff;
} }

View file

@ -23,9 +23,7 @@ KResultOr<FlatPtr> Process::sys$ttyname(int fd, Userspace<char*> buffer, size_t
auto tty_name = description->tty()->tty_name(); auto tty_name = description->tty()->tty_name();
if (size < tty_name.length() + 1) if (size < tty_name.length() + 1)
return ERANGE; return ERANGE;
if (!copy_to_user(buffer, tty_name.characters(), tty_name.length() + 1)) return copy_to_user(buffer, tty_name.characters(), tty_name.length() + 1);
return EFAULT;
return 0;
} }
KResultOr<FlatPtr> Process::sys$ptsname(int fd, Userspace<char*> buffer, size_t size) KResultOr<FlatPtr> Process::sys$ptsname(int fd, Userspace<char*> buffer, size_t size)
@ -41,9 +39,7 @@ KResultOr<FlatPtr> Process::sys$ptsname(int fd, Userspace<char*> buffer, size_t
auto pts_name = master_pty->pts_name(); auto pts_name = master_pty->pts_name();
if (size < pts_name.length() + 1) if (size < pts_name.length() + 1)
return ERANGE; return ERANGE;
if (!copy_to_user(buffer, pts_name.characters(), pts_name.length() + 1)) return copy_to_user(buffer, pts_name.characters(), pts_name.length() + 1);
return EFAULT;
return 0;
} }
} }

View file

@ -27,9 +27,7 @@ KResultOr<FlatPtr> Process::sys$uname(Userspace<utsname*> user_buf)
memcpy(buf.nodename, name.characters(), name.length() + 1); memcpy(buf.nodename, name.characters(), name.length() + 1);
}); });
if (!copy_to_user(user_buf, &buf)) return copy_to_user(user_buf, &buf);
return EFAULT;
return 0;
} }
} }

View file

@ -28,8 +28,7 @@ KResultOr<FlatPtr> Process::sys$unveil(Userspace<const Syscall::SC_unveil_params
{ {
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
Syscall::SC_unveil_params params; Syscall::SC_unveil_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
if (!params.path.characters && !params.permissions.characters) { if (!params.path.characters && !params.permissions.characters) {
m_veil_state = VeilState::Locked; m_veil_state = VeilState::Locked;

View file

@ -19,8 +19,7 @@ KResultOr<FlatPtr> Process::sys$utime(Userspace<const char*> user_path, size_t p
return path.error(); return path.error();
utimbuf buf; utimbuf buf;
if (user_buf) { if (user_buf) {
if (!copy_from_user(&buf, user_buf)) TRY(copy_from_user(&buf, user_buf));
return EFAULT;
} else { } else {
auto now = kgettimeofday().to_truncated_seconds(); auto now = kgettimeofday().to_truncated_seconds();
// Not a bug! // Not a bug!

View file

@ -25,8 +25,7 @@ KResultOr<FlatPtr> Process::sys$waitid(Userspace<const Syscall::SC_waitid_params
REQUIRE_PROMISE(proc); REQUIRE_PROMISE(proc);
Syscall::SC_waitid_params params; Syscall::SC_waitid_params params;
if (!copy_from_user(&params, user_params)) TRY(copy_from_user(&params, user_params));
return EFAULT;
Variant<Empty, NonnullRefPtr<Process>, NonnullRefPtr<ProcessGroup>> waitee = Empty {}; Variant<Empty, NonnullRefPtr<Process>, NonnullRefPtr<ProcessGroup>> waitee = Empty {};
switch (params.idtype) { switch (params.idtype) {
@ -59,9 +58,7 @@ KResultOr<FlatPtr> Process::sys$waitid(Userspace<const Syscall::SC_waitid_params
if (siginfo_or_error.is_error()) if (siginfo_or_error.is_error())
return siginfo_or_error.error(); return siginfo_or_error.error();
if (!copy_to_user(params.infop, &siginfo_or_error.value())) return copy_to_user(params.infop, &siginfo_or_error.value());
return EFAULT;
return 0;
} }
} }

View file

@ -26,8 +26,7 @@ KResultOr<FlatPtr> Process::sys$writev(int fd, Userspace<const struct iovec*> io
Vector<iovec, 32> vecs; Vector<iovec, 32> vecs;
if (!vecs.try_resize(iov_count)) if (!vecs.try_resize(iov_count))
return ENOMEM; return ENOMEM;
if (!copy_n_from_user(vecs.data(), iov, iov_count)) TRY(copy_n_from_user(vecs.data(), iov, iov_count));
return EFAULT;
for (auto& vec : vecs) { for (auto& vec : vecs) {
total_length += vec.iov_len; total_length += vec.iov_len;
if (total_length > NumericLimits<i32>::max()) if (total_length > NumericLimits<i32>::max())

View file

@ -472,9 +472,7 @@ KResult TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
case TIOCGPGRP: { case TIOCGPGRP: {
auto user_pgid = static_ptr_cast<pid_t*>(arg); auto user_pgid = static_ptr_cast<pid_t*>(arg);
auto pgid = this->pgid().value(); auto pgid = this->pgid().value();
if (!copy_to_user(user_pgid, &pgid)) return copy_to_user(user_pgid, &pgid);
return EFAULT;
return KSuccess;
} }
case TIOCSPGRP: { case TIOCSPGRP: {
ProcessGroupID pgid = static_cast<pid_t>(arg.ptr()); ProcessGroupID pgid = static_cast<pid_t>(arg.ptr());
@ -506,17 +504,14 @@ KResult TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
} }
case TCGETS: { case TCGETS: {
user_termios = static_ptr_cast<termios*>(arg); user_termios = static_ptr_cast<termios*>(arg);
if (!copy_to_user(user_termios, &m_termios)) return copy_to_user(user_termios, &m_termios);
return EFAULT;
return KSuccess;
} }
case TCSETS: case TCSETS:
case TCSETSF: case TCSETSF:
case TCSETSW: { case TCSETSW: {
user_termios = static_ptr_cast<termios*>(arg); user_termios = static_ptr_cast<termios*>(arg);
termios termios; termios termios;
if (!copy_from_user(&termios, user_termios)) TRY(copy_from_user(&termios, user_termios));
return EFAULT;
auto rc = set_termios(termios); auto rc = set_termios(termios);
if (request == TCSETSF) if (request == TCSETSF)
flush_input(); flush_input();
@ -539,14 +534,11 @@ KResult TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
ws.ws_col = m_columns; ws.ws_col = m_columns;
ws.ws_xpixel = 0; ws.ws_xpixel = 0;
ws.ws_ypixel = 0; ws.ws_ypixel = 0;
if (!copy_to_user(user_winsize, &ws)) return copy_to_user(user_winsize, &ws);
return EFAULT;
return KSuccess;
case TIOCSWINSZ: { case TIOCSWINSZ: {
user_winsize = static_ptr_cast<winsize*>(arg); user_winsize = static_ptr_cast<winsize*>(arg);
winsize ws; winsize ws;
if (!copy_from_user(&ws, user_winsize)) TRY(copy_from_user(&ws, user_winsize));
return EFAULT;
if (ws.ws_col == m_columns && ws.ws_row == m_rows) if (ws.ws_col == m_columns && ws.ws_row == m_rows)
return KSuccess; return KSuccess;
m_rows = ws.ws_row; m_rows = ws.ws_row;

View file

@ -802,10 +802,11 @@ bool Thread::has_signal_handler(u8 signal) const
return !action.handler_or_sigaction.is_null(); return !action.handler_or_sigaction.is_null();
} }
static bool push_value_on_user_stack(FlatPtr& stack, FlatPtr data) static void push_value_on_user_stack(FlatPtr& stack, FlatPtr data)
{ {
stack -= sizeof(FlatPtr); stack -= sizeof(FlatPtr);
return copy_to_user((FlatPtr*)stack, &data); auto result = copy_to_user((FlatPtr*)stack, &data);
VERIFY(result.is_success());
} }
void Thread::resume_from_stopped() void Thread::resume_from_stopped()

View file

@ -24,8 +24,7 @@ KResultOr<NonnullOwnPtr<KString>> UserOrKernelBuffer::try_copy_into_kstring(size
auto kstring = KString::try_create_uninitialized(size, buffer); auto kstring = KString::try_create_uninitialized(size, buffer);
if (!kstring) if (!kstring)
return ENOMEM; return ENOMEM;
if (!copy_from_user(buffer, m_buffer, size)) TRY(copy_from_user(buffer, m_buffer, size));
return EFAULT;
return kstring.release_nonnull(); return kstring.release_nonnull();
} }
@ -41,7 +40,7 @@ bool UserOrKernelBuffer::write(const void* src, size_t offset, size_t len)
return false; return false;
if (Memory::is_user_address(VirtualAddress(m_buffer))) if (Memory::is_user_address(VirtualAddress(m_buffer)))
return copy_to_user(m_buffer + offset, src, len); return copy_to_user(m_buffer + offset, src, len).is_success();
memcpy(m_buffer + offset, src, len); memcpy(m_buffer + offset, src, len);
return true; return true;
@ -53,7 +52,7 @@ bool UserOrKernelBuffer::read(void* dest, size_t offset, size_t len) const
return false; return false;
if (Memory::is_user_address(VirtualAddress(m_buffer))) if (Memory::is_user_address(VirtualAddress(m_buffer)))
return copy_from_user(dest, m_buffer + offset, len); return copy_from_user(dest, m_buffer + offset, len).is_success();
memcpy(dest, m_buffer + offset, len); memcpy(dest, m_buffer + offset, len);
return true; return true;
@ -65,7 +64,7 @@ bool UserOrKernelBuffer::memset(int value, size_t offset, size_t len)
return false; return false;
if (Memory::is_user_address(VirtualAddress(m_buffer))) if (Memory::is_user_address(VirtualAddress(m_buffer)))
return memset_user(m_buffer + offset, value, len); return memset_user(m_buffer + offset, value, len).is_success();
::memset(m_buffer + offset, value, len); ::memset(m_buffer + offset, value, len);
return true; return true;