Compare commits

...

11 Commits

Author SHA1 Message Date
Bananymous f022a1b08f Shell: Fix crash when executing semicolon
This fixes #4
2026-02-13 17:52:54 +02:00
Bananymous b3bbfaeff0 LibC: Fix posix_spawnattr_t definition 2026-02-10 01:22:25 +02:00
Bananymous 679a3d4209 LibGUI: Add Texture::clear{,_rect} 2026-02-08 19:45:01 +02:00
Bananymous a0211d88e7 Kernel: Don't include TCP header in MSS 2026-02-08 19:44:30 +02:00
Bananymous e216fc7798 Kernel: Fix port allocation endianness 2026-02-08 19:43:08 +02:00
Bananymous c648ea12f2 Kernel: Cleanup and fix UNIX sockets
EPOLLOUT is now sent to the correct socket and buffer is now a ring
buffer to avoid unnecessary memmove on every packet
2026-02-08 19:38:28 +02:00
Bananymous 2e59373a1e Kernel: Fix non blocking sockets blocking :D 2026-02-08 19:33:28 +02:00
Bananymous a51a81b6cd Kernel: Move {set,get}sockopt to sockets
Sockets can now actually implement socket options :D
2026-02-08 19:27:16 +02:00
Bananymous 9809f87010 LibC: Fix {read,write}v return value for partial actions 2026-02-08 18:45:29 +02:00
Bananymous 8794122c2d BAN: Variant allow copy/move from empty 2026-02-07 18:54:31 +02:00
Bananymous 8fb2270ecf DynamicLoader: map RO sections actually read only
I was mapping everything RW as i did not have mprotect when I
implemented the dynamic loader.
2026-02-04 23:21:06 +02:00
18 changed files with 282 additions and 109 deletions

View File

@ -126,14 +126,16 @@ namespace BAN
Variant(Variant&& other)
: m_index(other.m_index)
{
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
other.clear();
}
Variant(const Variant& other)
: m_index(other.m_index)
{
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
}
template<typename T>
@ -157,12 +159,13 @@ namespace BAN
Variant& operator=(Variant&& other)
{
if (m_index == other.m_index)
if (m_index == other.m_index && m_index != invalid_index())
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
else
{
clear();
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
m_index = other.m_index;
}
other.clear();
@ -171,12 +174,13 @@ namespace BAN
Variant& operator=(const Variant& other)
{
if (m_index == other.m_index)
if (m_index == other.m_index && m_index != invalid_index())
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
else
{
clear();
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
m_index = other.m_index;
}
return *this;

View File

@ -113,6 +113,8 @@ namespace Kernel
BAN::ErrorOr<size_t> recvmsg(msghdr& message, int flags);
BAN::ErrorOr<void> getsockname(sockaddr* address, socklen_t* address_len);
BAN::ErrorOr<void> getpeername(sockaddr* address, socklen_t* address_len);
BAN::ErrorOr<void> getsockopt(int level, int option, void* value, socklen_t* value_len);
BAN::ErrorOr<void> setsockopt(int level, int option, const void* value, socklen_t value_len);
// General API
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
@ -161,6 +163,8 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
// General API
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }

View File

@ -63,6 +63,7 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;

View File

@ -38,6 +38,7 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;

View File

@ -6,7 +6,6 @@
#include <kernel/FS/Socket.h>
#include <kernel/FS/TmpFS/Inode.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/OpenFileDescriptorSet.h>
namespace Kernel
@ -32,6 +31,8 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
virtual bool can_read_impl() const override;
virtual bool can_write_impl() const override;
@ -69,9 +70,10 @@ namespace Kernel
size_t size;
BAN::Vector<FDWrapper> fds;
BAN::Optional<struct ucred> ucred;
BAN::WeakPtr<UnixDomainSocket> sender;
};
BAN::ErrorOr<void> add_packet(const msghdr&, PacketInfo&&);
BAN::ErrorOr<size_t> add_packet(const msghdr&, PacketInfo&&, bool dont_block);
private:
const Socket::Type m_socket_type;
@ -81,10 +83,14 @@ namespace Kernel
BAN::CircularQueue<PacketInfo, 512> m_packet_infos;
size_t m_packet_size_total { 0 };
size_t m_packet_buffer_tail { 0 };
BAN::UniqPtr<VirtualRange> m_packet_buffer;
Mutex m_packet_lock;
mutable Mutex m_packet_lock;
ThreadBlocker m_packet_thread_blocker;
BAN::Atomic<size_t> m_sndbuf { 0 };
BAN::Atomic<size_t> m_bytes_sent { 0 };
friend class BAN::RefPtr<UnixDomainSocket>;
};

View File

@ -222,6 +222,22 @@ namespace Kernel
return getpeername_impl(address, address_len);
}
BAN::ErrorOr<void> Inode::getsockopt(int level, int option, void* value, socklen_t* value_len)
{
LockGuard _(m_mutex);
if (!mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
return getsockopt_impl(level, option, value, value_len);
}
BAN::ErrorOr<void> Inode::setsockopt(int level, int option, const void* value, socklen_t value_len)
{
LockGuard _(m_mutex);
if (!mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
return setsockopt_impl(level, option, value, value_len);
}
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
{
LockGuard _(m_mutex);

View File

@ -170,8 +170,8 @@ namespace Kernel
SpinLockGuard _(m_bound_socket_lock);
if (bind_address.sin_port == 0)
bind_address.sin_port = TRY(find_free_port());
const uint16_t port = BAN::host_to_network_endian(bind_address.sin_port);
bind_address.sin_port = BAN::host_to_network_endian(TRY(find_free_port()));
const uint16_t port = BAN::network_endian_to_host(bind_address.sin_port);
if (m_bound_sockets.contains(port))
return BAN::Error::from_errno(EADDRINUSE);

View File

@ -245,10 +245,7 @@ namespace Kernel
BAN::ErrorOr<size_t> TCPSocket::sendmsg_impl(const msghdr& message, int flags)
{
if (flags & MSG_NOSIGNAL)
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
if (flags != 0)
if (flags & ~(MSG_NOSIGNAL | MSG_DONTWAIT))
{
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
return BAN::Error::from_errno(ENOTSUP);
@ -264,6 +261,8 @@ namespace Kernel
{
if (m_state != State::Established)
return return_with_maybe_zero();
if (flags & MSG_DONTWAIT)
return BAN::Error::from_errno(EAGAIN);
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
}
@ -297,6 +296,34 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> TCPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{
if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
int result;
switch (option)
{
case SO_ERROR:
result = 0;
break;
case SO_SNDBUF:
result = m_send_window.scaled_size();
break;
case SO_RCVBUF:
result = m_recv_window.buffer->size();
break;
default:
return BAN::Error::from_errno(ENOTSUP);
}
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
memcpy(value, &result, len);
*value_len = sizeof(int);
return {};
}
BAN::ErrorOr<long> TCPSocket::ioctl_impl(int request, void* argument)
{
switch (request)
@ -436,7 +463,7 @@ namespace Kernel
};
auto interface = MUST(this->interface(reinterpret_cast<const sockaddr*>(&target), sizeof(target)));
add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, interface->payload_mtu() - m_network_layer.header_size());
add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, interface->payload_mtu() - m_network_layer.header_size() - protocol_header_size());
if (m_connection_info->has_window_scale)
add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift);

View File

@ -162,10 +162,7 @@ namespace Kernel
BAN::ErrorOr<size_t> UDPSocket::sendmsg_impl(const msghdr& message, int flags)
{
if (flags & MSG_NOSIGNAL)
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
if (flags != 0)
if (flags & ~(MSG_NOSIGNAL | MSG_DONTWAIT))
{
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
return BAN::Error::from_errno(ENOTSUP);
@ -213,6 +210,34 @@ namespace Kernel
return TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len));
}
BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{
if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
int result;
switch (option)
{
case SO_ERROR:
result = 0;
break;
case SO_SNDBUF:
result = m_packet_buffer->size();
break;
case SO_RCVBUF:
result = m_packet_buffer->size();
break;
default:
return BAN::Error::from_errno(ENOTSUP);
}
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
memcpy(value, &result, len);
*value_len = sizeof(int);
return {};
}
BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument)
{
switch (request)

View File

@ -25,7 +25,7 @@ namespace Kernel
static BAN::HashMap<BAN::RefPtr<Inode>, BAN::WeakPtr<UnixDomainSocket>, UnixSocketHash> s_bound_sockets;
static Mutex s_bound_socket_lock;
static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE;
static constexpr size_t s_packet_buffer_size = 0x10000;
static BAN::ErrorOr<BAN::StringView> validate_sockaddr_un(const sockaddr* address, socklen_t address_len)
{
@ -45,8 +45,6 @@ namespace Kernel
return BAN::StringView { sockaddr_un.sun_path, length };
}
// FIXME: why is this using spinlocks instead of mutexes??
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info)
{
auto socket = TRY(BAN::RefPtr<UnixDomainSocket>::create(socket_type, info));
@ -64,6 +62,7 @@ namespace Kernel
UnixDomainSocket::UnixDomainSocket(Socket::Type socket_type, const Socket::Info& info)
: Socket(info)
, m_socket_type(socket_type)
, m_sndbuf(s_packet_buffer_size)
{
switch (socket_type)
{
@ -289,28 +288,56 @@ namespace Kernel
case Socket::Type::SEQPACKET:
case Socket::Type::DGRAM:
return false;
default:
ASSERT_NOT_REACHED();
}
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<void> UnixDomainSocket::add_packet(const msghdr& packet, PacketInfo&& packet_info)
BAN::ErrorOr<size_t> UnixDomainSocket::add_packet(const msghdr& packet, PacketInfo&& packet_info, bool dont_block)
{
LockGuard _(m_packet_lock);
while (m_packet_infos.full() || m_packet_size_total + packet_info.size > s_packet_buffer_size)
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &m_packet_lock));
const auto has_space =
[&]() -> bool
{
if (m_packet_infos.full())
return false;
if (is_streaming())
return m_packet_size_total < m_packet_buffer->size();
return m_packet_size_total + packet_info.size <= m_packet_buffer->size();
};
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr() + m_packet_size_total);
size_t offset = 0;
for (int i = 0; i < packet.msg_iovlen; i++)
while (!has_space())
{
memcpy(packet_buffer + offset, packet.msg_iov[i].iov_base, packet.msg_iov[i].iov_len);
offset += packet.msg_iov[i].iov_len;
if (dont_block)
return BAN::Error::from_errno(EAGAIN);
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &m_packet_lock));
}
ASSERT(offset == packet_info.size);
if (auto available = m_packet_buffer->size() - m_packet_size_total; available < packet_info.size)
{
ASSERT(is_streaming());
packet_info.size = available;
}
uint8_t* packet_buffer_base_u8 = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
size_t bytes_copied = 0;
for (int i = 0; i < packet.msg_iovlen && bytes_copied < packet_info.size; i++)
{
const uint8_t* iov_base_u8 = static_cast<const uint8_t*>(packet.msg_iov[i].iov_base);
const size_t to_copy = BAN::Math::min(packet.msg_iov[i].iov_len, packet_info.size - bytes_copied);
const size_t copy_offset = (m_packet_buffer_tail + m_packet_size_total + bytes_copied) % m_packet_buffer->size();
const size_t before_wrap = BAN::Math::min(to_copy, m_packet_buffer->size() - copy_offset);
memcpy(packet_buffer_base_u8 + copy_offset, iov_base_u8, before_wrap);
if (const size_t after_wrap = to_copy - before_wrap)
memcpy(packet_buffer_base_u8, iov_base_u8 + before_wrap, after_wrap);
bytes_copied += to_copy;
}
ASSERT(bytes_copied == packet_info.size);
m_packet_size_total += packet_info.size;
m_packet_infos.emplace(BAN::move(packet_info));
@ -318,7 +345,7 @@ namespace Kernel
epoll_notify(EPOLLIN);
return {};
return bytes_copied;
}
bool UnixDomainSocket::can_read_impl() const
@ -334,24 +361,13 @@ namespace Kernel
return false;
}
LockGuard _(m_packet_lock);
return m_packet_size_total > 0;
}
bool UnixDomainSocket::can_write_impl() const
{
if (m_info.has<ConnectionInfo>())
{
auto& connection_info = m_info.get<ConnectionInfo>();
auto connection = connection_info.connection.lock();
if (!connection)
return false;
if (connection->m_packet_infos.full())
return false;
if (connection->m_packet_size_total >= s_packet_buffer_size)
return false;
}
return true;
return m_bytes_sent < m_sndbuf;
}
bool UnixDomainSocket::has_hungup_impl() const
@ -375,6 +391,7 @@ namespace Kernel
}
LockGuard _(m_packet_lock);
while (m_packet_size_total == 0)
{
if (m_info.has<ConnectionInfo>())
@ -395,7 +412,7 @@ namespace Kernel
cheader->cmsg_len = message.msg_controllen;
size_t cheader_len = 0;
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
uint8_t* packet_buffer_base_u8 = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
message.msg_flags = 0;
@ -469,7 +486,12 @@ namespace Kernel
uint8_t* iov_base = static_cast<uint8_t*>(iov.iov_base);
const size_t nrecv = BAN::Math::min<size_t>(iov.iov_len - iov_offset, packet_info.size - packet_received);
memcpy(iov_base + iov_offset, packet_buffer + packet_received, nrecv);
const size_t copy_offset = (m_packet_buffer_tail + packet_received) % m_packet_buffer->size();
const size_t before_wrap = BAN::Math::min<size_t>(nrecv, m_packet_buffer->size() - copy_offset);
memcpy(iov_base + iov_offset, packet_buffer_base_u8 + copy_offset, before_wrap);
if (const size_t after_wrap = nrecv - before_wrap)
memcpy(iov_base + iov_offset + before_wrap, packet_buffer_base_u8, after_wrap);
packet_received += nrecv;
@ -490,12 +512,17 @@ namespace Kernel
if (packet_info.size == 0)
m_packet_infos.pop();
// FIXME: get rid of this memmove :)
memmove(packet_buffer, packet_buffer + to_discard, m_packet_size_total - to_discard);
m_packet_buffer_tail = (m_packet_buffer_tail + to_discard) % m_packet_buffer->size();
m_packet_size_total -= to_discard;
total_recv += packet_received;
if (auto sender = packet_info.sender.lock())
{
sender->m_bytes_sent -= to_discard;
sender->epoll_notify(EPOLLOUT);
}
// on linux ancillary data is a barrier on stream sockets, lets do the same
if (!is_streaming() || had_ancillary_data)
break;
@ -505,17 +532,12 @@ namespace Kernel
m_packet_thread_blocker.unblock();
epoll_notify(EPOLLOUT);
return total_recv;
}
BAN::ErrorOr<size_t> UnixDomainSocket::sendmsg_impl(const msghdr& message, int flags)
{
if (flags & MSG_NOSIGNAL)
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
if (flags != 0)
if (flags & ~(MSG_NOSIGNAL | MSG_DONTWAIT))
{
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
return BAN::Error::from_errno(ENOTSUP);
@ -529,13 +551,14 @@ namespace Kernel
return result;
}();
if (total_message_size > s_packet_buffer_size)
return BAN::Error::from_errno(ENOBUFS);
if (!is_streaming() && total_message_size > m_packet_buffer->size())
return BAN::Error::from_errno(EMSGSIZE);
PacketInfo packet_info {
.size = total_message_size,
.fds = {},
.ucred = {},
.size = total_message_size,
.fds = {},
.ucred = {},
.sender = TRY(get_weak_ptr()),
};
for (const auto* header = CMSG_FIRSTHDR(&message); header; header = CMSG_NXTHDR(&message, header))
@ -608,8 +631,9 @@ namespace Kernel
auto target = connection_info.connection.lock();
if (!target)
return BAN::Error::from_errno(ENOTCONN);
TRY(target->add_packet(message, BAN::move(packet_info)));
return total_message_size;
const size_t bytes_sent = TRY(target->add_packet(message, BAN::move(packet_info), flags & MSG_DONTWAIT));
m_bytes_sent += bytes_sent;
return bytes_sent;
}
else
{
@ -626,7 +650,7 @@ namespace Kernel
Process::current().root_file().inode,
Process::current().credentials(),
absolute_path,
O_RDWR
O_WRONLY
)).inode;
}
else
@ -652,9 +676,11 @@ namespace Kernel
if (!target)
return BAN::Error::from_errno(EDESTADDRREQ);
TRY(target->add_packet(message, BAN::move(packet_info)));
return total_message_size;
if (target->m_socket_type != m_socket_type)
return BAN::Error::from_errno(EPROTOTYPE);
const auto bytes_sent = TRY(target->add_packet(message, BAN::move(packet_info), flags & MSG_DONTWAIT));
m_bytes_sent += bytes_sent;
return bytes_sent;
}
}
@ -678,4 +704,58 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> UnixDomainSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{
if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
int result;
switch (option)
{
case SO_ERROR:
result = 0;
break;
case SO_SNDBUF:
result = m_sndbuf;
break;
case SO_RCVBUF:
result = m_packet_buffer->size();
break;
default:
dwarnln("getsockopt(SOL_SOCKET, {})", option);
return BAN::Error::from_errno(ENOTSUP);
}
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
memcpy(value, &result, len);
*value_len = sizeof(int);
return {};
}
BAN::ErrorOr<void> UnixDomainSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
{
if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
switch (option)
{
case SO_SNDBUF:
{
if (value_len != sizeof(int))
return BAN::Error::from_errno(EINVAL);
const int new_sndbuf = *static_cast<const int*>(value);
if (new_sndbuf < 0)
return BAN::Error::from_errno(EINVAL);
m_sndbuf = new_sndbuf;
break;
}
default:
dwarnln("setsockopt(SOL_SOCKET, {})", option);
return BAN::Error::from_errno(ENOTSUP);
}
return {};
}
}

View File

@ -795,7 +795,7 @@ namespace Kernel
LockGuard _(inode->m_mutex);
if (is_nonblock && !inode->can_read())
return BAN::Error::from_errno(EWOULDBLOCK);
return BAN::Error::from_errno(EAGAIN);
return inode->recvmsg(message, flags);
}
@ -817,12 +817,13 @@ namespace Kernel
LockGuard _(inode->m_mutex);
if (inode->has_hungup())
{
Thread::current().add_signal(SIGPIPE, {});
if (!(flags & MSG_NOSIGNAL))
Thread::current().add_signal(SIGPIPE, {});
return BAN::Error::from_errno(EPIPE);
}
if (is_nonblock && !inode->can_write())
return BAN::Error::from_errno(EWOULDBLOCK);
return inode->sendmsg(message, flags);
return BAN::Error::from_errno(EAGAIN);
return inode->sendmsg(message, flags | (is_nonblock ? MSG_DONTWAIT : 0));
}
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const

View File

@ -1674,20 +1674,13 @@ namespace Kernel
if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
switch (option_name)
{
case SO_ERROR:
{
option_len = BAN::Math::min<socklen_t>(option_len, sizeof(int));
const int zero { 0 };
TRY(write_to_user(user_option_value, &zero, option_len));
TRY(write_to_user(user_option_len, &option_len, sizeof(socklen_t)));
return 0;
}
}
auto* buffer = TRY(validate_and_pin_pointer_access(user_option_value, option_len, true));
BAN::ScopeGuard _([buffer] { buffer->unpin(); });
dwarnln("getsockopt(SOL_SOCKET, {})", option_name);
return BAN::Error::from_errno(ENOTSUP);
TRY(inode->getsockopt(level, option_name, user_option_value, &option_len));
TRY(write_to_user(user_option_len, &option_len, sizeof(socklen_t)));
return 0;
}
BAN::ErrorOr<long> Process::sys_setsockopt(int socket, int level, int option_name, const void* user_option_value, socklen_t option_len)
@ -1705,10 +1698,12 @@ namespace Kernel
if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK);
(void)user_option_value;
auto* buffer = TRY(validate_and_pin_pointer_access(user_option_value, option_len, false));
BAN::ScopeGuard _([buffer] { buffer->unpin(); });
dwarnln("setsockopt(SOL_SOCKET, {})", option_name);
return BAN::Error::from_errno(ENOTSUP);
TRY(inode->setsockopt(level, option_name, user_option_value, option_len));
return 0;
}
BAN::ErrorOr<long> Process::sys_accept(int socket, sockaddr* address, socklen_t* address_len, int flags)

View File

@ -18,7 +18,7 @@ typedef struct
{
short flags;
pid_t pgroup;
sched_param schedparam;
struct sched_param schedparam;
int schedpolicy;
sigset_t sigdefault;
sigset_t sigmask;

View File

@ -123,14 +123,15 @@ struct linger
#define SOMAXCONN 4096
#define MSG_CTRUNC 0x01
#define MSG_DONTROUTE 0x02
#define MSG_EOR 0x04
#define MSG_OOB 0x08
#define MSG_NOSIGNAL 0x10
#define MSG_PEEK 0x20
#define MSG_TRUNC 0x40
#define MSG_WAITALL 0x80
#define MSG_CTRUNC 0x001
#define MSG_DONTROUTE 0x002
#define MSG_EOR 0x004
#define MSG_OOB 0x008
#define MSG_NOSIGNAL 0x010
#define MSG_PEEK 0x020
#define MSG_TRUNC 0x040
#define MSG_WAITALL 0x080
#define MSG_DONTWAIT 0x100
#define AF_UNSPEC 0
#define AF_INET 1

View File

@ -20,9 +20,10 @@ ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
if (ret <= 0)
return result;
nread += ret;
result += ret;
}
result += nread;
}
return result;
}
@ -44,8 +45,9 @@ ssize_t writev(int fildes, const struct iovec* iov, int iovcnt)
if (ret <= 0)
return result;
nwrite += ret;
result += ret;
}
result += nwrite;
}
return result;
}

View File

@ -45,6 +45,9 @@ namespace LibGUI
void fill_rect(int32_t x, int32_t y, uint32_t width, uint32_t height, uint32_t color);
void fill(uint32_t color) { return fill_rect(0, 0, width(), height(), color); }
void clear_rect(int32_t x, int32_t y, uint32_t width, uint32_t height) { fill_rect(x, y, width, height, m_bg_color); }
void clear() { return clear_rect(0, 0, width(), height()); }
void copy_texture(const Texture& texture, int32_t x, int32_t y, uint32_t sub_x = 0, uint32_t sub_y = 0, uint32_t width = -1, uint32_t height = -1);
void draw_character(uint32_t codepoint, const LibFont::Font& font, int32_t x, int32_t y, uint32_t color);

View File

@ -373,8 +373,6 @@ static void handle_copy_relocation(const LoadedElf& elf, const RelocT& reloc)
reinterpret_cast<void*>(src_elf->base + src_sym->st_value),
symbol.st_size
);
src_sym->st_value = (elf.base + reloc.r_offset) - src_elf->base;
}
template<typename RelocT> requires BAN::is_same_v<RelocT, ElfNativeRelocation> || BAN::is_same_v<RelocT, ElfNativeRelocationA>
@ -927,6 +925,8 @@ static bool can_load_elf(int fd, const ElfNativeFileHeader& file_header, uintptr
return true;
}
// FIXME: Don't map read-only sections as writable with DT_TEXTREL.
// Instead mprotect the areas writable during relocation.
static void load_program_header(const ElfNativeProgramHeader& program_header, int fd, bool needs_writable)
{
if (program_header.p_type != PT_LOAD)
@ -966,7 +966,7 @@ static void load_program_header(const ElfNativeProgramHeader& program_header, in
mmap_args.flags = MAP_PRIVATE | MAP_FIXED;
mmap_args.len = file_backed_size;
mmap_args.off = program_header.p_offset;
mmap_args.prot = prot | PROT_WRITE;
mmap_args.prot = prot | (needs_writable ? PROT_WRITE : 0);
if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(program_header.p_vaddr))
print_error_and_exit("could not load program header", ret);
@ -1002,12 +1002,13 @@ static void load_program_header(const ElfNativeProgramHeader& program_header, in
0x00,
program_header.p_memsz - program_header.p_filesz
);
}
if (!(prot & PROT_WRITE) && !needs_writable)
{
// FIXME: Implement mprotect so PROT_WRITE can be removed
//syscall(SYS_MPROTECT, start_vaddr, length, prot);
if (!(prot & PROT_WRITE) && !needs_writable)
{
if (auto ret = syscall(SYS_MPROTECT, program_header.p_vaddr + file_backed_size, program_header.p_memsz - file_backed_size, prot))
print_error_and_exit("failed to remove PROT_WRITE from mapped", ret);
print(STDDBG_FILENO, "dropped PROT_WRITE :nekocatwoah:");
}
}
}

View File

@ -274,6 +274,12 @@ BAN::ErrorOr<void> Execute::execute_command(const PipedCommand& piped_command)
}
);
if (piped_command.commands[i].arguments.empty())
{
child_codes[i] = 0;
continue;
}
const int fd_in = last_pipe_rd;
const int fd_out = new_pipe[1];