Kernel: Support non-null-terminated paths in sockaddr_un
This commit is contained in:
@@ -21,7 +21,7 @@ namespace Kernel
|
|||||||
|
|
||||||
static BAN::ErrorOr<BAN::StringView> validate_sockaddr_un(const sockaddr* address, socklen_t address_len)
|
static BAN::ErrorOr<BAN::StringView> validate_sockaddr_un(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
if (address_len < static_cast<socklen_t>(sizeof(sa_family_t)))
|
if (address_len <= static_cast<socklen_t>(sizeof(sa_family_t)))
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
if (address_len > static_cast<socklen_t>(sizeof(sockaddr_un)))
|
if (address_len > static_cast<socklen_t>(sizeof(sockaddr_un)))
|
||||||
address_len = sizeof(sockaddr_un);
|
address_len = sizeof(sockaddr_un);
|
||||||
@@ -30,13 +30,12 @@ namespace Kernel
|
|||||||
if (sockaddr_un.sun_family != AF_UNIX)
|
if (sockaddr_un.sun_family != AF_UNIX)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
size_t length = 0;
|
auto sun_path = BAN::StringView { sockaddr_un.sun_path, address_len - sizeof(sa_family_t) };
|
||||||
while (length < sizeof(sockaddr_un::sun_path) && sockaddr_un.sun_path[length])
|
if (const auto null_idx = sun_path.find('\0'); null_idx.has_value())
|
||||||
length++;
|
sun_path = sun_path.substring(0, null_idx.value());
|
||||||
if (length >= sizeof(sockaddr_un::sun_path))
|
if (sun_path.empty())
|
||||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
return sun_path;
|
||||||
return BAN::StringView { sockaddr_un.sun_path, length };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info)
|
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info)
|
||||||
@@ -264,14 +263,15 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> UnixDomainSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> UnixDomainSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
||||||
if (sun_path.empty())
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
BAN::String sun_path_nul;
|
||||||
|
TRY(sun_path_nul.append(sun_path));
|
||||||
|
|
||||||
// FIXME: This feels sketchy
|
// FIXME: This feels sketchy
|
||||||
auto parent_file = sun_path.front() == '/'
|
auto parent_file = sun_path.front() == '/'
|
||||||
? TRY(Process::current().root_file().clone())
|
? TRY(Process::current().root_file().clone())
|
||||||
: TRY(Process::current().working_directory().clone());
|
: TRY(Process::current().working_directory().clone());
|
||||||
if (auto ret = Process::current().create_file(AT_FDCWD, sun_path.data(), 0755 | Inode::Mode::IFSOCK); ret.is_error())
|
if (auto ret = Process::current().create_file(AT_FDCWD, sun_path_nul.data(), 0755 | Inode::Mode::IFSOCK); ret.is_error())
|
||||||
{
|
{
|
||||||
if (ret.error().get_error_code() == EEXIST)
|
if (ret.error().get_error_code() == EEXIST)
|
||||||
return BAN::Error::from_errno(EADDRINUSE);
|
return BAN::Error::from_errno(EADDRINUSE);
|
||||||
|
|||||||
Reference in New Issue
Block a user