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

Kernel: Modify the IOCTL API to return KResult

The kernel has been gradually moving towards KResult from just bare
int's, this change migrates the IOCTL paths.
This commit is contained in:
Brian Gianforcaro 2021-07-26 03:47:25 -07:00 committed by Ali Mohammad Pur
parent 46c9b1d81c
commit de9ff0af50
16 changed files with 151 additions and 151 deletions

View file

@ -311,38 +311,38 @@ KResultOr<size_t> KeyboardDevice::write(FileDescription&, u64, const UserOrKerne
return 0; return 0;
} }
int KeyboardDevice::ioctl(FileDescription&, unsigned request, Userspace<void*> arg) KResult KeyboardDevice::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
{ {
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)) if (!copy_to_user(output, &m_num_lock_on))
return -EFAULT; return EFAULT;
return 0; 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.
auto num_lock_value = static_cast<u8>(arg.ptr()); auto num_lock_value = static_cast<u8>(arg.ptr());
if (num_lock_value != 0 && num_lock_value != 1) if (num_lock_value != 0 && num_lock_value != 1)
return -EINVAL; return EINVAL;
m_num_lock_on = !!num_lock_value; m_num_lock_on = !!num_lock_value;
return 0; return KSuccess;
} }
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)) if (!copy_to_user(output, &m_caps_lock_on))
return -EFAULT; return EFAULT;
return 0; 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());
if (caps_lock_value != 0 && caps_lock_value != 1) if (caps_lock_value != 0 && caps_lock_value != 1)
return -EINVAL; return EINVAL;
m_caps_lock_on = !!caps_lock_value; m_caps_lock_on = !!caps_lock_value;
return 0; return KSuccess;
} }
default: default:
return -EINVAL; return EINVAL;
}; };
} }

View file

@ -37,7 +37,7 @@ public:
virtual mode_t required_mode() const override { return 0440; } virtual mode_t required_mode() const override { return 0440; }
// ^File // ^File
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override; virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
virtual String device_name() const override { return String::formatted("keyboard{}", minor()); } virtual String device_name() const override { return String::formatted("keyboard{}", minor()); }

View file

@ -35,9 +35,9 @@ KResult File::close()
return KSuccess; return KSuccess;
} }
int File::ioctl(FileDescription&, unsigned, Userspace<void*>) KResult File::ioctl(FileDescription&, unsigned, Userspace<void*>)
{ {
return -ENOTTY; return ENOTTY;
} }
KResultOr<Region*> File::mmap(Process&, FileDescription&, const Range&, u64, int, bool) KResultOr<Region*> File::mmap(Process&, FileDescription&, const Range&, u64, int, bool)

View file

@ -87,7 +87,7 @@ public:
virtual void did_seek(FileDescription&, off_t) { } virtual void did_seek(FileDescription&, off_t) { }
virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) = 0; virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) = 0;
virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) = 0; virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) = 0;
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg); virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg);
virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared); virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared);
virtual KResult stat(::stat&) const { return EBADF; } virtual KResult stat(::stat&) const { return EBADF; }

View file

@ -62,34 +62,34 @@ KResultOr<size_t> InodeFile::write(FileDescription& description, u64 offset, con
return nwritten; return nwritten;
} }
int InodeFile::ioctl(FileDescription& description, unsigned request, Userspace<void*> arg) KResult InodeFile::ioctl(FileDescription& description, unsigned request, Userspace<void*> arg)
{ {
(void)description; (void)description;
switch (request) { switch (request) {
case FIBMAP: { case FIBMAP: {
if (!Process::current()->is_superuser()) if (!Process::current()->is_superuser())
return -EPERM; return EPERM;
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)) if (!copy_from_user(&block_number, user_block_number))
return -EFAULT; return EFAULT;
if (block_number < 0) if (block_number < 0)
return -EINVAL; return EINVAL;
auto block_address = inode().get_block_address(block_number); auto block_address = inode().get_block_address(block_number);
if (block_address.is_error()) if (block_address.is_error())
return block_address.error(); return block_address.error();
if (!copy_to_user(user_block_number, &block_address.value())) if (!copy_to_user(user_block_number, &block_address.value()))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
default: default:
return -EINVAL; return EINVAL;
} }
} }

View file

@ -32,7 +32,7 @@ public:
virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override; virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override;
virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override; virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override;
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override; virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override; virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override;
virtual KResult stat(::stat& buffer) const override { return inode().metadata().stat(buffer); } virtual KResult stat(::stat& buffer) const override { return inode().metadata().stat(buffer); }

View file

@ -143,7 +143,7 @@ size_t FramebufferDevice::framebuffer_size_in_bytes() const
return m_framebuffer_pitch * m_framebuffer_height; return m_framebuffer_pitch * m_framebuffer_height;
} }
int FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*> arg) KResult FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
{ {
REQUIRE_PROMISE(video); REQUIRE_PROMISE(video);
switch (request) { switch (request) {
@ -151,26 +151,26 @@ int FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*
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)) if (!copy_to_user(user_size, &value))
return -EFAULT; return EFAULT;
return 0; 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)) if (!copy_to_user(user_index, &value))
return -EFAULT; return EFAULT;
if (!m_graphics_adapter->double_framebuffering_capable()) if (!m_graphics_adapter->double_framebuffering_capable())
return -ENOTIMPL; return ENOTIMPL;
return 0; return KSuccess;
} }
case FB_IOCTL_SET_BUFFER: { case FB_IOCTL_SET_BUFFER: {
auto buffer = static_cast<int>(arg.ptr()); auto buffer = static_cast<int>(arg.ptr());
if (buffer != 0 && buffer != 1) if (buffer != 0 && buffer != 1)
return -EINVAL; return EINVAL;
if (!m_graphics_adapter->double_framebuffering_capable()) if (!m_graphics_adapter->double_framebuffering_capable())
return -ENOTIMPL; return ENOTIMPL;
m_graphics_adapter->set_y_offset(m_output_port_index, buffer == 0 ? 0 : m_framebuffer_height); m_graphics_adapter->set_y_offset(m_output_port_index, buffer == 0 ? 0 : m_framebuffer_height);
return 0; 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);
@ -179,24 +179,24 @@ int FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*
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)) if (!copy_to_user(user_resolution, &resolution))
return -EFAULT; return EFAULT;
return 0; 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)) if (!copy_from_user(&resolution, user_resolution))
return -EFAULT; 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;
if (!m_graphics_adapter->modesetting_capable()) { if (!m_graphics_adapter->modesetting_capable()) {
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)) if (!copy_to_user(user_resolution, &resolution))
return -EFAULT; return EFAULT;
return -ENOTIMPL; return ENOTIMPL;
} }
if (!m_graphics_adapter->try_to_set_resolution(m_output_port_index, resolution.width, resolution.height)) { if (!m_graphics_adapter->try_to_set_resolution(m_output_port_index, resolution.width, resolution.height)) {
@ -210,8 +210,8 @@ int FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*
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)) if (!copy_to_user(user_resolution, &resolution))
return -EFAULT; return EFAULT;
return -EINVAL; return EINVAL;
} }
m_framebuffer_width = resolution.width; m_framebuffer_width = resolution.width;
m_framebuffer_height = resolution.height; m_framebuffer_height = resolution.height;
@ -222,25 +222,25 @@ int FramebufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*
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)) if (!copy_to_user(user_resolution, &resolution))
return -EFAULT; return EFAULT;
return 0; 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)) if (!copy_from_user(&buffer_offset, user_buffer_offset))
return -EFAULT; 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)) if (!copy_to_user(user_buffer_offset, &buffer_offset))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case FB_IOCTL_FLUSH_BUFFERS: case FB_IOCTL_FLUSH_BUFFERS:
return -ENOTSUP; return ENOTSUP;
default: default:
return -EINVAL; return EINVAL;
}; };
} }

View file

@ -22,7 +22,7 @@ class FramebufferDevice : public BlockDevice {
public: public:
static NonnullRefPtr<FramebufferDevice> create(const GraphicsDevice&, size_t, PhysicalAddress, size_t, size_t, size_t); static NonnullRefPtr<FramebufferDevice> create(const GraphicsDevice&, size_t, PhysicalAddress, size_t, size_t, size_t);
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override; virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override; virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override;
// ^Device // ^Device

View file

@ -140,7 +140,7 @@ void FrameBufferDevice::set_buffer(int buffer_index)
buffer.dirty_rect = {}; buffer.dirty_rect = {};
} }
int FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*> arg) KResult FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
{ {
REQUIRE_PROMISE(video); REQUIRE_PROMISE(video);
switch (request) { switch (request) {
@ -148,20 +148,20 @@ int FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*
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)) if (!copy_to_user(out, &value))
return -EFAULT; return EFAULT;
return 0; 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)) if (!copy_from_user(&resolution, user_resolution))
return -EFAULT; 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)) if (!copy_to_user(user_resolution, &resolution))
return -EFAULT; return EFAULT;
return 0; 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);
@ -170,33 +170,33 @@ int FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*
resolution.width = width(); resolution.width = width();
resolution.height = height(); resolution.height = height();
if (!copy_to_user(user_resolution, &resolution)) if (!copy_to_user(user_resolution, &resolution))
return -EFAULT; return EFAULT;
return 0; 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());
if (!is_valid_buffer_index(buffer_index)) if (!is_valid_buffer_index(buffer_index))
return -EINVAL; return EINVAL;
if (m_last_set_buffer_index.exchange(buffer_index) != buffer_index && m_are_writes_active) if (m_last_set_buffer_index.exchange(buffer_index) != buffer_index && m_are_writes_active)
set_buffer(buffer_index); set_buffer(buffer_index);
return 0; return KSuccess;
} }
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)) if (!copy_from_user(&flush_rects, user_flush_rects))
return -EFAULT; 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)))
return -EFAULT; return EFAULT;
if (m_are_writes_active && flush_rects.count > 0) { if (m_are_writes_active && flush_rects.count > 0) {
auto& buffer = buffer_from_index(flush_rects.buffer_index); auto& buffer = buffer_from_index(flush_rects.buffer_index);
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])) if (!copy_from_user(&user_dirty_rect, &flush_rects.rects[i]))
return -EFAULT; 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,
@ -222,22 +222,22 @@ int FrameBufferDevice::ioctl(FileDescription&, unsigned request, Userspace<void*
} }
} }
} }
return 0; 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)) if (!copy_from_user(&buffer_offset, user_buffer_offset))
return -EFAULT; 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)) if (!copy_to_user(user_buffer_offset, &buffer_offset))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
default: default:
return -EINVAL; return EINVAL;
}; };
} }

View file

@ -60,7 +60,7 @@ private:
void create_buffer(Buffer&, size_t, size_t); void create_buffer(Buffer&, size_t, size_t);
void set_buffer(int); void set_buffer(int);
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override; virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override; virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override;
virtual bool can_read(const FileDescription&, size_t) const override { return true; } virtual bool can_read(const FileDescription&, size_t) const override { return true; }
virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override { return EINVAL; } virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override { return EINVAL; }

View file

@ -568,75 +568,75 @@ KResult IPv4Socket::getsockopt(FileDescription& description, int level, int opti
} }
} }
int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg) KResult IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
{ {
REQUIRE_PROMISE(inet); REQUIRE_PROMISE(inet);
auto ioctl_route = [request, arg]() { 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)) if (!copy_from_user(&route, user_route))
return -EFAULT; return EFAULT;
auto copied_ifname = copy_string_from_user(route.rt_dev, IFNAMSIZ); auto copied_ifname = copy_string_from_user(route.rt_dev, IFNAMSIZ);
if (copied_ifname.is_null()) if (copied_ifname.is_null())
return -EFAULT; return EFAULT;
auto adapter = NetworkingManagement::the().lookup_by_name(copied_ifname); auto adapter = NetworkingManagement::the().lookup_by_name(copied_ifname);
if (!adapter) if (!adapter)
return -ENODEV; return ENODEV;
switch (request) { switch (request) {
case SIOCADDRT: case SIOCADDRT:
if (!Process::current()->is_superuser()) if (!Process::current()->is_superuser())
return -EPERM; return EPERM;
if (route.rt_gateway.sa_family != AF_INET) if (route.rt_gateway.sa_family != AF_INET)
return -EAFNOSUPPORT; return EAFNOSUPPORT;
if ((route.rt_flags & (RTF_UP | RTF_GATEWAY)) != (RTF_UP | RTF_GATEWAY)) if ((route.rt_flags & (RTF_UP | RTF_GATEWAY)) != (RTF_UP | RTF_GATEWAY))
return -EINVAL; // FIXME: Find the correct value to return return EINVAL; // FIXME: Find the correct value to return
adapter->set_ipv4_gateway(IPv4Address(((sockaddr_in&)route.rt_gateway).sin_addr.s_addr)); adapter->set_ipv4_gateway(IPv4Address(((sockaddr_in&)route.rt_gateway).sin_addr.s_addr));
return 0; return KSuccess;
case SIOCDELRT: case SIOCDELRT:
// FIXME: Support gateway deletion // FIXME: Support gateway deletion
return 0; return KSuccess;
} }
return -EINVAL; return EINVAL;
}; };
auto ioctl_arp = [request, arg]() { 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)) if (!copy_from_user(&arp_req, user_req))
return -EFAULT; return EFAULT;
switch (request) { switch (request) {
case SIOCSARP: case SIOCSARP:
if (!Process::current()->is_superuser()) if (!Process::current()->is_superuser())
return -EPERM; return EPERM;
if (arp_req.arp_pa.sa_family != AF_INET) if (arp_req.arp_pa.sa_family != AF_INET)
return -EAFNOSUPPORT; return EAFNOSUPPORT;
update_arp_table(IPv4Address(((sockaddr_in&)arp_req.arp_pa).sin_addr.s_addr), *(MACAddress*)&arp_req.arp_ha.sa_data[0], UpdateArp::Set); update_arp_table(IPv4Address(((sockaddr_in&)arp_req.arp_pa).sin_addr.s_addr), *(MACAddress*)&arp_req.arp_ha.sa_data[0], UpdateArp::Set);
return 0; return KSuccess;
case SIOCDARP: case SIOCDARP:
if (!Process::current()->is_superuser()) if (!Process::current()->is_superuser())
return -EPERM; return EPERM;
if (arp_req.arp_pa.sa_family != AF_INET) if (arp_req.arp_pa.sa_family != AF_INET)
return -EAFNOSUPPORT; return EAFNOSUPPORT;
update_arp_table(IPv4Address(((sockaddr_in&)arp_req.arp_pa).sin_addr.s_addr), *(MACAddress*)&arp_req.arp_ha.sa_data[0], UpdateArp::Delete); update_arp_table(IPv4Address(((sockaddr_in&)arp_req.arp_pa).sin_addr.s_addr), *(MACAddress*)&arp_req.arp_ha.sa_data[0], UpdateArp::Delete);
return 0; return KSuccess;
} }
return -EINVAL; return EINVAL;
}; };
auto ioctl_interface = [request, arg]() { 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)) if (!copy_from_user(&ifr, user_ifr))
return -EFAULT; return EFAULT;
char namebuf[IFNAMSIZ + 1]; char namebuf[IFNAMSIZ + 1];
memcpy(namebuf, ifr.ifr_name, IFNAMSIZ); memcpy(namebuf, ifr.ifr_name, IFNAMSIZ);
@ -644,24 +644,24 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
auto adapter = NetworkingManagement::the().lookup_by_name(namebuf); auto adapter = NetworkingManagement::the().lookup_by_name(namebuf);
if (!adapter) if (!adapter)
return -ENODEV; return ENODEV;
switch (request) { switch (request) {
case SIOCSIFADDR: case SIOCSIFADDR:
if (!Process::current()->is_superuser()) if (!Process::current()->is_superuser())
return -EPERM; return EPERM;
if (ifr.ifr_addr.sa_family != AF_INET) if (ifr.ifr_addr.sa_family != AF_INET)
return -EAFNOSUPPORT; return EAFNOSUPPORT;
adapter->set_ipv4_address(IPv4Address(((sockaddr_in&)ifr.ifr_addr).sin_addr.s_addr)); adapter->set_ipv4_address(IPv4Address(((sockaddr_in&)ifr.ifr_addr).sin_addr.s_addr));
return 0; return KSuccess;
case SIOCSIFNETMASK: case SIOCSIFNETMASK:
if (!Process::current()->is_superuser()) if (!Process::current()->is_superuser())
return -EPERM; return EPERM;
if (ifr.ifr_addr.sa_family != AF_INET) if (ifr.ifr_addr.sa_family != AF_INET)
return -EAFNOSUPPORT; return EAFNOSUPPORT;
adapter->set_ipv4_netmask(IPv4Address(((sockaddr_in&)ifr.ifr_netmask).sin_addr.s_addr)); adapter->set_ipv4_netmask(IPv4Address(((sockaddr_in&)ifr.ifr_netmask).sin_addr.s_addr));
return 0; return KSuccess;
case SIOCGIFADDR: { case SIOCGIFADDR: {
auto ip4_addr = adapter->ipv4_address().to_u32(); auto ip4_addr = adapter->ipv4_address().to_u32();
@ -669,8 +669,8 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_to_user(user_ifr, &ifr))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case SIOCGIFNETMASK: { case SIOCGIFNETMASK: {
@ -681,8 +681,8 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_to_user(user_ifr, &ifr))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case SIOCGIFHWADDR: { case SIOCGIFHWADDR: {
@ -690,8 +690,8 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_to_user(user_ifr, &ifr))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case SIOCGIFBRDADDR: { case SIOCGIFBRDADDR: {
@ -703,8 +703,8 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_to_user(user_ifr, &ifr))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case SIOCGIFMTU: { case SIOCGIFMTU: {
@ -713,8 +713,8 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_to_user(user_ifr, &ifr))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case SIOCGIFFLAGS: { case SIOCGIFFLAGS: {
@ -723,17 +723,17 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_to_user(user_ifr, &ifr))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case SIOCGIFCONF: { case SIOCGIFCONF: {
// FIXME: stub! // FIXME: stub!
return -EINVAL; return EINVAL;
} }
} }
return -EINVAL; return EINVAL;
}; };
switch (request) { switch (request) {
@ -757,7 +757,7 @@ int IPv4Socket::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
return ioctl_arp(); return ioctl_arp();
} }
return -EINVAL; return EINVAL;
} }
KResult IPv4Socket::close() KResult IPv4Socket::close()

View file

@ -46,7 +46,7 @@ public:
virtual KResult setsockopt(int level, int option, Userspace<const void*>, socklen_t) override; virtual KResult setsockopt(int level, int option, Userspace<const void*>, socklen_t) override;
virtual KResult getsockopt(FileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override; virtual KResult getsockopt(FileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override; virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
bool did_receive(const IPv4Address& peer_address, u16 peer_port, ReadonlyBytes, const Time&); bool did_receive(const IPv4Address& peer_address, u16 peer_port, ReadonlyBytes, const Time&);

View file

@ -106,14 +106,14 @@ KResult MasterPTY::close()
return KSuccess; return KSuccess;
} }
int MasterPTY::ioctl(FileDescription& description, unsigned request, Userspace<void*> arg) KResult MasterPTY::ioctl(FileDescription& description, unsigned request, Userspace<void*> arg)
{ {
REQUIRE_PROMISE(tty); REQUIRE_PROMISE(tty);
if (!m_slave) if (!m_slave)
return -EIO; return EIO;
if (request == TIOCSWINSZ || request == TIOCGPGRP) if (request == TIOCSWINSZ || request == TIOCGPGRP)
return m_slave->ioctl(description, request, arg); return m_slave->ioctl(description, request, arg);
return -EINVAL; return EINVAL;
} }
String MasterPTY::absolute_path(const FileDescription&) const String MasterPTY::absolute_path(const FileDescription&) const

View file

@ -40,7 +40,7 @@ private:
virtual bool can_write(const FileDescription&, size_t) const override; virtual bool can_write(const FileDescription&, size_t) const override;
virtual KResult close() override; virtual KResult close() override;
virtual bool is_master_pty() const override { return true; } virtual bool is_master_pty() const override { return true; }
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override; virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
virtual StringView class_name() const override { return "MasterPTY"; } virtual StringView class_name() const override { return "MasterPTY"; }
RefPtr<SlavePTY> m_slave; RefPtr<SlavePTY> m_slave;

View file

@ -360,9 +360,9 @@ void TTY::flush_input()
evaluate_block_conditions(); evaluate_block_conditions();
} }
int TTY::set_termios(const termios& t) KResult TTY::set_termios(const termios& t)
{ {
int rc = 0; KResult rc = KSuccess;
m_termios = t; m_termios = t;
dbgln_if(TTY_DEBUG, "{} set_termios: ECHO={}, ISIG={}, ICANON={}, ECHOE={}, ECHOK={}, ECHONL={}, ISTRIP={}, ICRNL={}, INLCR={}, IGNCR={}, OPOST={}, ONLCR={}", dbgln_if(TTY_DEBUG, "{} set_termios: ECHO={}, ISIG={}, ICANON={}, ECHOE={}, ECHOK={}, ECHONL={}, ISTRIP={}, ICRNL={}, INLCR={}, IGNCR={}, OPOST={}, ONLCR={}",
@ -402,7 +402,7 @@ int TTY::set_termios(const termios& t)
for (auto flag : unimplemented_iflags) { for (auto flag : unimplemented_iflags) {
if (m_termios.c_iflag & flag.value) { if (m_termios.c_iflag & flag.value) {
dbgln("FIXME: iflag {} unimplemented", flag.name); dbgln("FIXME: iflag {} unimplemented", flag.name);
rc = -ENOTIMPL; rc = ENOTIMPL;
} }
} }
@ -416,7 +416,7 @@ int TTY::set_termios(const termios& t)
for (auto flag : unimplemented_oflags) { for (auto flag : unimplemented_oflags) {
if (m_termios.c_oflag & flag.value) { if (m_termios.c_oflag & flag.value) {
dbgln("FIXME: oflag {} unimplemented", flag.name); dbgln("FIXME: oflag {} unimplemented", flag.name);
rc = -ENOTIMPL; rc = ENOTIMPL;
} }
} }
@ -436,7 +436,7 @@ int TTY::set_termios(const termios& t)
for (auto flag : unimplemented_cflags) { for (auto flag : unimplemented_cflags) {
if (m_termios.c_cflag & flag.value) { if (m_termios.c_cflag & flag.value) {
dbgln("FIXME: cflag {} unimplemented", flag.name); dbgln("FIXME: cflag {} unimplemented", flag.name);
rc = -ENOTIMPL; rc = ENOTIMPL;
} }
} }
@ -447,14 +447,14 @@ int TTY::set_termios(const termios& t)
for (auto flag : unimplemented_lflags) { for (auto flag : unimplemented_lflags) {
if (m_termios.c_lflag & flag.value) { if (m_termios.c_lflag & flag.value) {
dbgln("FIXME: lflag {} unimplemented", flag.name); dbgln("FIXME: lflag {} unimplemented", flag.name);
rc = -ENOTIMPL; rc = ENOTIMPL;
} }
} }
return rc; return rc;
} }
int TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg) KResult TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
{ {
REQUIRE_PROMISE(tty); REQUIRE_PROMISE(tty);
auto& current_process = *Process::current(); auto& current_process = *Process::current();
@ -473,42 +473,42 @@ int TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_to_user(user_pgid, &pgid))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case TIOCSPGRP: { case TIOCSPGRP: {
ProcessGroupID pgid = static_cast<pid_t>(arg.ptr()); ProcessGroupID pgid = static_cast<pid_t>(arg.ptr());
if (pgid <= 0) if (pgid <= 0)
return -EINVAL; return EINVAL;
InterruptDisabler disabler; InterruptDisabler disabler;
auto process_group = ProcessGroup::from_pgid(pgid); auto process_group = ProcessGroup::from_pgid(pgid);
// Disallow setting a nonexistent PGID. // Disallow setting a nonexistent PGID.
if (!process_group) if (!process_group)
return -EINVAL; return EINVAL;
auto process = Process::from_pid(ProcessID(pgid.value())); auto process = Process::from_pid(ProcessID(pgid.value()));
SessionID new_sid = process ? process->sid() : Process::get_sid_from_pgid(pgid); SessionID new_sid = process ? process->sid() : Process::get_sid_from_pgid(pgid);
if (!new_sid || new_sid != current_process.sid()) if (!new_sid || new_sid != current_process.sid())
return -EPERM; return EPERM;
if (process && pgid != process->pgid()) if (process && pgid != process->pgid())
return -EPERM; return EPERM;
m_pg = process_group; m_pg = process_group;
if (process) { if (process) {
if (auto parent = Process::from_pid(process->ppid())) { if (auto parent = Process::from_pid(process->ppid())) {
m_original_process_parent = *parent; m_original_process_parent = *parent;
return 0; return KSuccess;
} }
} }
m_original_process_parent = nullptr; m_original_process_parent = nullptr;
return 0; return KSuccess;
} }
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)) if (!copy_to_user(user_termios, &m_termios))
return -EFAULT; return EFAULT;
return 0; return KSuccess;
} }
case TCSETS: case TCSETS:
case TCSETSF: case TCSETSF:
@ -516,8 +516,8 @@ int TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
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)) if (!copy_from_user(&termios, user_termios))
return -EFAULT; return EFAULT;
int rc = set_termios(termios); auto rc = set_termios(termios);
if (request == TCSETSF) if (request == TCSETSF)
flush_input(); flush_input();
return rc; return rc;
@ -528,9 +528,9 @@ int TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
if (operation == TCIFLUSH || operation == TCIOFLUSH) { if (operation == TCIFLUSH || operation == TCIOFLUSH) {
flush_input(); flush_input();
} else if (operation != TCOFLUSH) { } else if (operation != TCOFLUSH) {
return -EINVAL; return EINVAL;
} }
return 0; return KSuccess;
} }
case TIOCGWINSZ: case TIOCGWINSZ:
user_winsize = static_ptr_cast<winsize*>(arg); user_winsize = static_ptr_cast<winsize*>(arg);
@ -540,30 +540,30 @@ int TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
ws.ws_xpixel = 0; ws.ws_xpixel = 0;
ws.ws_ypixel = 0; ws.ws_ypixel = 0;
if (!copy_to_user(user_winsize, &ws)) if (!copy_to_user(user_winsize, &ws))
return -EFAULT; return EFAULT;
return 0; 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)) if (!copy_from_user(&ws, user_winsize))
return -EFAULT; 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 0; return KSuccess;
m_rows = ws.ws_row; m_rows = ws.ws_row;
m_columns = ws.ws_col; m_columns = ws.ws_col;
generate_signal(SIGWINCH); generate_signal(SIGWINCH);
return 0; return KSuccess;
} }
case TIOCSCTTY: case TIOCSCTTY:
current_process.set_tty(this); current_process.set_tty(this);
return 0; return KSuccess;
case TIOCSTI: case TIOCSTI:
return -EIO; return EIO;
case TIOCNOTTY: case TIOCNOTTY:
current_process.set_tty(nullptr); current_process.set_tty(nullptr);
return 0; return KSuccess;
} }
return -EINVAL; return EINVAL;
} }
void TTY::set_size(unsigned short columns, unsigned short rows) void TTY::set_size(unsigned short columns, unsigned short rows)

View file

@ -25,7 +25,7 @@ public:
virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override; virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override;
virtual bool can_read(const FileDescription&, size_t) const override; virtual bool can_read(const FileDescription&, size_t) const override;
virtual bool can_write(const FileDescription&, size_t) const override; virtual bool can_write(const FileDescription&, size_t) const override;
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override final; virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override final;
virtual String absolute_path(const FileDescription&) const override { return tty_name(); } virtual String absolute_path(const FileDescription&) const override { return tty_name(); }
virtual String const& tty_name() const = 0; virtual String const& tty_name() const = 0;
@ -40,7 +40,7 @@ public:
return 0; return 0;
} }
int set_termios(const termios&); KResult set_termios(const termios&);
bool should_generate_signals() const { return m_termios.c_lflag & ISIG; } bool should_generate_signals() const { return m_termios.c_lflag & ISIG; }
bool should_flush_on_signal() const { return !(m_termios.c_lflag & NOFLSH); } bool should_flush_on_signal() const { return !(m_termios.c_lflag & NOFLSH); }
bool should_echo_input() const { return m_termios.c_lflag & ECHO; } bool should_echo_input() const { return m_termios.c_lflag & ECHO; }