Kernel/LibC: Implement chroot

This commit is contained in:
Bananymous 2025-08-11 02:29:49 +03:00
parent 695262624d
commit 309ec660b6
15 changed files with 116 additions and 80 deletions

View File

@ -20,6 +20,6 @@ namespace Kernel::ELF
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions; BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
}; };
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode>, const Credentials&, PageTable&); BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials&, PageTable&);
} }

View File

@ -71,13 +71,13 @@ namespace Kernel
File root_file() File root_file()
{ {
return File(root_inode(), "/"_sv); return File { root_inode(), "/"_sv };
} }
BAN::ErrorOr<File> file_from_relative_path(const File& parent, const Credentials&, BAN::StringView, int); BAN::ErrorOr<File> file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials&, BAN::StringView, int);
BAN::ErrorOr<File> file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags) BAN::ErrorOr<File> file_from_absolute_path(BAN::RefPtr<Inode> root_inode, const Credentials& credentials, BAN::StringView path, int flags)
{ {
return file_from_relative_path(root_file(), credentials, path, flags); return file_from_relative_path(root_inode, File { root_inode, "/"_sv }, credentials, path, flags);
} }
private: private:

View File

@ -5,6 +5,7 @@
#include <BAN/WeakPtr.h> #include <BAN/WeakPtr.h>
#include <kernel/FS/Socket.h> #include <kernel/FS/Socket.h>
#include <kernel/FS/TmpFS/Inode.h> #include <kernel/FS/TmpFS/Inode.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/Lock/SpinLock.h> #include <kernel/Lock/SpinLock.h>
namespace Kernel namespace Kernel
@ -39,8 +40,8 @@ namespace Kernel
BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan); BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan);
bool is_bound() const { return !m_bound_path.empty(); } bool is_bound() const { return !m_bound_file.canonical_path.empty(); }
bool is_bound_to_unused() const { return m_bound_path == "X"_sv; } bool is_bound_to_unused() const { return !m_bound_file.inode; }
bool is_streaming() const; bool is_streaming() const;
@ -63,7 +64,7 @@ namespace Kernel
private: private:
const Socket::Type m_socket_type; const Socket::Type m_socket_type;
BAN::String m_bound_path; VirtualFileSystem::File m_bound_file;
BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info; BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info;

View File

@ -76,6 +76,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_getcwd(char* buffer, size_t size); BAN::ErrorOr<long> sys_getcwd(char* buffer, size_t size);
BAN::ErrorOr<long> sys_chdir(const char* path); BAN::ErrorOr<long> sys_chdir(const char* path);
BAN::ErrorOr<long> sys_fchdir(int fildes); BAN::ErrorOr<long> sys_fchdir(int fildes);
BAN::ErrorOr<long> sys_chroot(const char* path);
BAN::ErrorOr<long> sys_setuid(uid_t); BAN::ErrorOr<long> sys_setuid(uid_t);
BAN::ErrorOr<long> sys_setgid(gid_t); BAN::ErrorOr<long> sys_setgid(gid_t);
@ -234,6 +235,7 @@ namespace Kernel
static void update_alarm_queue(); static void update_alarm_queue();
const VirtualFileSystem::File& working_directory() const { return m_working_directory; } const VirtualFileSystem::File& working_directory() const { return m_working_directory; }
const VirtualFileSystem::File& root_file() const { return m_root_file; }
private: private:
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp); Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
@ -313,6 +315,7 @@ namespace Kernel
mutable Mutex m_process_lock; mutable Mutex m_process_lock;
VirtualFileSystem::File m_working_directory; VirtualFileSystem::File m_working_directory;
VirtualFileSystem::File m_root_file;
BAN::Vector<Thread*> m_threads; BAN::Vector<Thread*> m_threads;

View File

@ -104,7 +104,7 @@ namespace Kernel::ELF
return BAN::move(program_headers); return BAN::move(program_headers);
} }
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> inode, const Credentials& credentials, PageTable& page_table) BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials& credentials, PageTable& page_table)
{ {
auto file_header = TRY(read_and_validate_file_header(inode)); auto file_header = TRY(read_and_validate_file_header(inode));
auto program_headers = TRY(read_program_headers(inode, file_header)); auto program_headers = TRY(read_program_headers(inode, file_header));
@ -143,7 +143,7 @@ namespace Kernel::ELF
if (!interpreter.empty()) if (!interpreter.empty())
{ {
auto interpreter_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, interpreter, O_EXEC)).inode; auto interpreter_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(root, credentials, interpreter, O_EXEC)).inode;
auto interpreter_file_header = TRY(read_and_validate_file_header(interpreter_inode)); auto interpreter_file_header = TRY(read_and_validate_file_header(interpreter_inode));
auto interpreter_program_headers = TRY(read_program_headers(interpreter_inode, interpreter_file_header)); auto interpreter_program_headers = TRY(read_program_headers(interpreter_inode, interpreter_file_header));

View File

@ -186,7 +186,8 @@ namespace Kernel
BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::StringView block_device_path, BAN::StringView target) BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::StringView block_device_path, BAN::StringView target)
{ {
auto block_device_file = TRY(file_from_absolute_path(credentials, block_device_path, true)); // TODO: allow custom root
auto block_device_file = TRY(file_from_absolute_path(root_inode(), credentials, block_device_path, true));
if (!block_device_file.inode->is_device()) if (!block_device_file.inode->is_device())
return BAN::Error::from_errno(ENOTBLK); return BAN::Error::from_errno(ENOTBLK);
@ -200,7 +201,8 @@ namespace Kernel
BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::RefPtr<FileSystem> file_system, BAN::StringView path) BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::RefPtr<FileSystem> file_system, BAN::StringView path)
{ {
auto file = TRY(file_from_absolute_path(credentials, path, true)); // TODO: allow custom root
auto file = TRY(file_from_absolute_path(root_inode(), credentials, path, true));
if (!file.inode->mode().ifdir()) if (!file.inode->mode().ifdir())
return BAN::Error::from_errno(ENOTDIR); return BAN::Error::from_errno(ENOTDIR);
@ -227,7 +229,7 @@ namespace Kernel
return nullptr; return nullptr;
} }
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(const File& parent, const Credentials& credentials, BAN::StringView path, int flags) BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials& credentials, BAN::StringView path, int flags)
{ {
LockGuard _(m_mutex); LockGuard _(m_mutex);
@ -269,6 +271,8 @@ namespace Kernel
auto orig = inode; auto orig = inode;
// resolve file name // resolve file name
{
if (!(inode == root_inode && path_part == ".."_sv))
{ {
auto parent_inode = inode; auto parent_inode = inode;
if (path_part == ".."_sv) if (path_part == ".."_sv)
@ -277,6 +281,7 @@ namespace Kernel
if (!parent_inode->can_access(credentials, O_SEARCH)) if (!parent_inode->can_access(credentials, O_SEARCH))
return BAN::Error::from_errno(EACCES); return BAN::Error::from_errno(EACCES);
inode = TRY(parent_inode->find_inode(path_part)); inode = TRY(parent_inode->find_inode(path_part));
}
if (path_part == ".."_sv) if (path_part == ".."_sv)
{ {
@ -310,7 +315,7 @@ namespace Kernel
if (link_target.front() == '/') if (link_target.front() == '/')
{ {
inode = root_inode(); inode = root_inode;
canonical_path.clear(); canonical_path.clear();
} }
else else

View File

@ -13,7 +13,15 @@
namespace Kernel namespace Kernel
{ {
static BAN::HashMap<BAN::String, BAN::WeakPtr<UnixDomainSocket>> s_bound_sockets; struct UnixSocketHash
{
BAN::hash_t operator()(const BAN::RefPtr<Inode>& socket)
{
return BAN::hash<const Inode*>{}(socket.ptr());
}
};
static BAN::HashMap<BAN::RefPtr<Inode>, BAN::WeakPtr<UnixDomainSocket>, UnixSocketHash> s_bound_sockets;
static SpinLock s_bound_socket_lock; static SpinLock s_bound_socket_lock;
static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE; static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE;
@ -57,9 +65,7 @@ namespace Kernel
if (is_bound() && !is_bound_to_unused()) if (is_bound() && !is_bound_to_unused())
{ {
SpinLockGuard _(s_bound_socket_lock); SpinLockGuard _(s_bound_socket_lock);
auto it = s_bound_sockets.find(m_bound_path); s_bound_sockets.remove(m_bound_file.inode);
if (it != s_bound_sockets.end())
s_bound_sockets.remove(it);
} }
if (m_info.has<ConnectionInfo>()) if (m_info.has<ConnectionInfo>())
{ {
@ -117,17 +123,22 @@ namespace Kernel
return_inode = reinterpret_cast<UnixDomainSocket*>(return_inode_tmp.ptr()); return_inode = reinterpret_cast<UnixDomainSocket*>(return_inode_tmp.ptr());
} }
TRY(return_inode->m_bound_path.push_back('X')); TRY(return_inode->m_bound_file.canonical_path.push_back('X'));
return_inode->m_info.get<ConnectionInfo>().connection = TRY(pending->get_weak_ptr()); return_inode->m_info.get<ConnectionInfo>().connection = TRY(pending->get_weak_ptr());
pending->m_info.get<ConnectionInfo>().connection = TRY(return_inode->get_weak_ptr()); pending->m_info.get<ConnectionInfo>().connection = TRY(return_inode->get_weak_ptr());
pending->m_info.get<ConnectionInfo>().connection_done = true; pending->m_info.get<ConnectionInfo>().connection_done = true;
if (address && address_len && !is_bound_to_unused()) if (address && address_len && !is_bound_to_unused())
{ {
size_t copy_len = BAN::Math::min<size_t>(*address_len, sizeof(sockaddr) + m_bound_path.size() + 1); sockaddr_un sa_un {
auto& sockaddr_un = *reinterpret_cast<struct sockaddr_un*>(address); .sun_family = AF_UNIX,
sockaddr_un.sun_family = AF_UNIX; .sun_path {},
strncpy(sockaddr_un.sun_path, pending->m_bound_path.data(), copy_len); };
strcpy(sa_un.sun_path, pending->m_bound_file.canonical_path.data());
const size_t to_copy = BAN::Math::min<size_t>(*address_len, sizeof(sockaddr_un));
memcpy(address, &sa_un, to_copy);
*address_len = to_copy;
} }
return TRY(Process::current().open_inode(VirtualFileSystem::File(return_inode, "<unix socket>"_sv), O_RDWR | flags)); return TRY(Process::current().open_inode(VirtualFileSystem::File(return_inode, "<unix socket>"_sv), O_RDWR | flags));
@ -141,10 +152,11 @@ namespace Kernel
if (sockaddr_un.sun_family != AF_UNIX) if (sockaddr_un.sun_family != AF_UNIX)
return BAN::Error::from_errno(EAFNOSUPPORT); return BAN::Error::from_errno(EAFNOSUPPORT);
if (!is_bound()) if (!is_bound())
TRY(m_bound_path.push_back('X')); TRY(m_bound_file.canonical_path.push_back('X'));
auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path)); auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path));
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path( auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(
Process::current().root_file().inode,
Process::current().credentials(), Process::current().credentials(),
absolute_path, absolute_path,
O_RDWR O_RDWR
@ -154,7 +166,7 @@ namespace Kernel
{ {
SpinLockGuard _(s_bound_socket_lock); SpinLockGuard _(s_bound_socket_lock);
auto it = s_bound_sockets.find(file.canonical_path); auto it = s_bound_sockets.find(file.inode);
if (it == s_bound_sockets.end()) if (it == s_bound_sockets.end())
return BAN::Error::from_errno(ECONNREFUSED); return BAN::Error::from_errno(ECONNREFUSED);
target = it->value.lock(); target = it->value.lock();
@ -236,7 +248,7 @@ namespace Kernel
// FIXME: This feels sketchy // FIXME: This feels sketchy
auto parent_file = bind_path.front() == '/' auto parent_file = bind_path.front() == '/'
? VirtualFileSystem::get().root_file() ? 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_or_dir(AT_FDCWD, bind_path.data(), 0755 | S_IFSOCK); ret.is_error()) if (auto ret = Process::current().create_file_or_dir(AT_FDCWD, bind_path.data(), 0755 | S_IFSOCK); ret.is_error())
{ {
@ -245,6 +257,7 @@ namespace Kernel
return ret.release_error(); return ret.release_error();
} }
auto file = TRY(VirtualFileSystem::get().file_from_relative_path( auto file = TRY(VirtualFileSystem::get().file_from_relative_path(
Process::current().root_file().inode,
parent_file, parent_file,
Process::current().credentials(), Process::current().credentials(),
bind_path, bind_path,
@ -252,10 +265,10 @@ namespace Kernel
)); ));
SpinLockGuard _(s_bound_socket_lock); SpinLockGuard _(s_bound_socket_lock);
if (s_bound_sockets.contains(file.canonical_path)) if (s_bound_sockets.contains(file.inode))
return BAN::Error::from_errno(EADDRINUSE); return BAN::Error::from_errno(EADDRINUSE);
TRY(s_bound_sockets.emplace(file.canonical_path, TRY(get_weak_ptr()))); TRY(s_bound_sockets.emplace(file.inode, TRY(get_weak_ptr())));
m_bound_path = BAN::move(file.canonical_path); m_bound_file = BAN::move(file);
return {}; return {};
} }
@ -354,14 +367,21 @@ namespace Kernel
} }
else else
{ {
BAN::String canonical_path; BAN::RefPtr<Inode> target_inode;
if (!address) if (!address)
{ {
auto& connectionless_info = m_info.get<ConnectionlessInfo>(); auto& connectionless_info = m_info.get<ConnectionlessInfo>();
if (connectionless_info.peer_address.empty()) if (connectionless_info.peer_address.empty())
return BAN::Error::from_errno(EDESTADDRREQ); return BAN::Error::from_errno(EDESTADDRREQ);
TRY(canonical_path.append(connectionless_info.peer_address));
auto absolute_path = TRY(Process::current().absolute_path_of(connectionless_info.peer_address));
target_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(
Process::current().root_file().inode,
Process::current().credentials(),
absolute_path,
O_RDWR
)).inode;
} }
else else
{ {
@ -372,17 +392,16 @@ namespace Kernel
return BAN::Error::from_errno(EAFNOSUPPORT); return BAN::Error::from_errno(EAFNOSUPPORT);
auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path)); auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path));
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path( target_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(
Process::current().root_file().inode,
Process::current().credentials(), Process::current().credentials(),
absolute_path, absolute_path,
O_WRONLY O_WRONLY
)); )).inode;
canonical_path = BAN::move(file.canonical_path);
} }
SpinLockGuard _(s_bound_socket_lock); SpinLockGuard _(s_bound_socket_lock);
auto it = s_bound_sockets.find(canonical_path); auto it = s_bound_sockets.find(target_inode);
if (it == s_bound_sockets.end()) if (it == s_bound_sockets.end())
return BAN::Error::from_errno(EDESTADDRREQ); return BAN::Error::from_errno(EDESTADDRREQ);
auto target = it->value.lock(); auto target = it->value.lock();
@ -449,20 +468,11 @@ namespace Kernel
if (!connection) if (!connection)
return BAN::Error::from_errno(ENOTCONN); return BAN::Error::from_errno(ENOTCONN);
sockaddr_un sa_un; sockaddr_un sa_un {
sa_un.sun_family = AF_UNIX; .sun_family = AF_UNIX,
sa_un.sun_path[0] = 0; .sun_path = {},
};
{ strcpy(sa_un.sun_path, connection->m_bound_file.canonical_path.data());
SpinLockGuard _(s_bound_socket_lock);
for (auto& [path, socket] : s_bound_sockets)
{
if (socket.lock() != connection)
continue;
strcpy(sa_un.sun_path, path.data());
break;
}
}
const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len); const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len);
memcpy(address, &sa_un, to_copy); memcpy(address, &sa_un, to_copy);

View File

@ -77,7 +77,7 @@ namespace Kernel
BAN::ErrorOr<int> OpenFileDescriptorSet::open(BAN::StringView absolute_path, int flags) BAN::ErrorOr<int> OpenFileDescriptorSet::open(BAN::StringView absolute_path, int flags)
{ {
return open(TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags)), flags); return open(TRY(VirtualFileSystem::get().file_from_absolute_path(Process::current().root_file().inode, m_credentials, absolute_path, flags)), flags);
} }
struct SocketInfo struct SocketInfo

View File

@ -103,6 +103,8 @@ namespace Kernel
auto* process = create_process(credentials, 0); auto* process = create_process(credentials, 0);
process->m_working_directory = VirtualFileSystem::get().root_file(); process->m_working_directory = VirtualFileSystem::get().root_file();
process->m_root_file = VirtualFileSystem::get().root_file();
process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace())); process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace()));
TRY(process->m_cmdline.emplace_back()); TRY(process->m_cmdline.emplace_back());
@ -118,7 +120,7 @@ namespace Kernel
auto executable_file = TRY(process->find_file(AT_FDCWD, path.data(), O_EXEC)); auto executable_file = TRY(process->find_file(AT_FDCWD, path.data(), O_EXEC));
auto executable_inode = executable_file.inode; auto executable_inode = executable_file.inode;
auto executable = TRY(ELF::load_from_inode(executable_inode, process->m_credentials, process->page_table())); auto executable = TRY(ELF::load_from_inode(process->m_root_file.inode, executable_inode, process->m_credentials, process->page_table()));
process->m_mapped_regions = BAN::move(executable.regions); process->m_mapped_regions = BAN::move(executable.regions);
if (executable_inode->mode().mode & +Inode::Mode::ISUID) if (executable_inode->mode().mode & +Inode::Mode::ISUID)
@ -456,7 +458,7 @@ namespace Kernel
auto parent_file = TRY(find_relative_parent(fd, path)); auto parent_file = TRY(find_relative_parent(fd, path));
auto file = path auto file = path
? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags)) ? TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent_file, m_credentials, path, flags))
: BAN::move(parent_file); : BAN::move(parent_file);
return file; return file;
@ -480,7 +482,7 @@ namespace Kernel
if (auto index = path_sv.rfind('/'); index.has_value()) if (auto index = path_sv.rfind('/'); index.has_value())
{ {
parent = TRY(VirtualFileSystem::get().file_from_relative_path(relative_parent, m_credentials, path_sv.substring(0, index.value()), flags)); parent = TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, relative_parent, m_credentials, path_sv.substring(0, index.value()), flags));
file_name = path_sv.substring(index.value() + 1); file_name = path_sv.substring(index.value() + 1);
} }
else else
@ -510,7 +512,7 @@ namespace Kernel
ASSERT(m_process_lock.is_locked()); ASSERT(m_process_lock.is_locked());
if (path && path[0] == '/') if (path && path[0] == '/')
return VirtualFileSystem::get().root_file(); return TRY(m_root_file.clone());
if (fd == AT_FDCWD) if (fd == AT_FDCWD)
return TRY(m_working_directory.clone()); return TRY(m_working_directory.clone());
@ -582,6 +584,7 @@ namespace Kernel
} }
auto working_directory = TRY(m_working_directory.clone()); auto working_directory = TRY(m_working_directory.clone());
auto root_file = TRY(m_root_file.clone());
BAN::Vector<BAN::String> cmdline; BAN::Vector<BAN::String> cmdline;
TRY(cmdline.resize(m_cmdline.size())); TRY(cmdline.resize(m_cmdline.size()));
@ -604,6 +607,7 @@ namespace Kernel
Process* forked = create_process(m_credentials, m_pid, m_sid, m_pgrp); Process* forked = create_process(m_credentials, m_pid, m_sid, m_pgrp);
forked->m_controlling_terminal = m_controlling_terminal; forked->m_controlling_terminal = m_controlling_terminal;
forked->m_working_directory = BAN::move(working_directory); forked->m_working_directory = BAN::move(working_directory);
forked->m_root_file = BAN::move(root_file);
forked->m_cmdline = BAN::move(cmdline); forked->m_cmdline = BAN::move(cmdline);
forked->m_environ = BAN::move(environ); forked->m_environ = BAN::move(environ);
forked->m_page_table = BAN::move(page_table); forked->m_page_table = BAN::move(page_table);
@ -656,7 +660,7 @@ namespace Kernel
auto executable_file = TRY(find_file(AT_FDCWD, path, O_EXEC)); auto executable_file = TRY(find_file(AT_FDCWD, path, O_EXEC));
auto executable_inode = executable_file.inode; auto executable_inode = executable_file.inode;
auto executable = TRY(ELF::load_from_inode(executable_inode, m_credentials, *new_page_table)); auto executable = TRY(ELF::load_from_inode(m_root_file.inode, executable_inode, m_credentials, *new_page_table));
auto new_mapped_regions = BAN::move(executable.regions); auto new_mapped_regions = BAN::move(executable.regions);
BAN::Vector<LibELF::AuxiliaryVector> auxiliary_vector; BAN::Vector<LibELF::AuxiliaryVector> auxiliary_vector;
@ -1044,7 +1048,7 @@ namespace Kernel
TRY(validate_string_access(path)); TRY(validate_string_access(path));
auto [parent, file_name] = TRY(find_parent_file(fd, path, O_RDONLY)); auto [parent, file_name] = TRY(find_parent_file(fd, path, O_RDONLY));
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, file_name, flags); auto file_or_error = VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent, m_credentials, file_name, flags);
VirtualFileSystem::File file; VirtualFileSystem::File file;
if (file_or_error.is_error()) if (file_or_error.is_error())
@ -1054,7 +1058,7 @@ namespace Kernel
// FIXME: There is a race condition between next two lines // FIXME: There is a race condition between next two lines
TRY(parent.inode->create_file(file_name, (mode & 0777) | Inode::Mode::IFREG, m_credentials.euid(), m_credentials.egid())); TRY(parent.inode->create_file(file_name, (mode & 0777) | Inode::Mode::IFREG, m_credentials.euid(), m_credentials.egid()));
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, file_name, flags & ~O_RDWR)); file = TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent, m_credentials, file_name, flags & ~O_RDWR));
} }
else else
{ {
@ -1135,7 +1139,7 @@ namespace Kernel
credentials.set_egid(credentials.rgid()); credentials.set_egid(credentials.rgid());
auto relative_parent = TRY(find_relative_parent(AT_FDCWD, path)); auto relative_parent = TRY(find_relative_parent(AT_FDCWD, path));
TRY(VirtualFileSystem::get().file_from_relative_path(relative_parent, credentials, path, flags)); TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, relative_parent, credentials, path, flags));
return 0; return 0;
} }
@ -1258,6 +1262,7 @@ namespace Kernel
flag = O_NOFOLLOW; flag = O_NOFOLLOW;
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
TRY(validate_string_access(path));
auto inode = TRY(find_file(fd, path, flag)).inode; auto inode = TRY(find_file(fd, path, flag)).inode;
@ -1280,6 +1285,7 @@ namespace Kernel
flag = O_NOFOLLOW; flag = O_NOFOLLOW;
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
TRY(validate_string_access(path));
auto inode = TRY(find_file(fd, path, flag)).inode; auto inode = TRY(find_file(fd, path, flag)).inode;
@ -2095,22 +2101,25 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_chdir(const char* path) BAN::ErrorOr<long> Process::sys_chdir(const char* path)
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
TRY(validate_string_access(path)); TRY(validate_string_access(path));
m_working_directory = TRY(find_file(AT_FDCWD, path, O_SEARCH));
auto file = TRY(find_file(AT_FDCWD, path, O_SEARCH));
m_working_directory = BAN::move(file);
return 0; return 0;
} }
BAN::ErrorOr<long> Process::sys_fchdir(int fildes) BAN::ErrorOr<long> Process::sys_fchdir(int fildes)
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
m_working_directory = TRY(m_open_file_descriptors.file_of(fildes));
return 0;
}
auto file = TRY(m_open_file_descriptors.file_of(fildes)); BAN::ErrorOr<long> Process::sys_chroot(const char* path)
m_working_directory = BAN::move(file); {
LockGuard _(m_process_lock);
TRY(validate_string_access(path));
if (!m_credentials.is_superuser())
return BAN::Error::from_errno(EACCES);
m_root_file = TRY(find_file(AT_FDCWD, path, O_SEARCH));
return 0; return 0;
} }

View File

@ -121,8 +121,8 @@ namespace Kernel
void TTY::keyboard_task(void*) void TTY::keyboard_task(void*)
{ {
BAN::RefPtr<Inode> keyboard_inode; BAN::RefPtr<Inode> keyboard_inode;
if (auto ret = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/keyboard"_sv, O_RDONLY); !ret.is_error()) if (auto ret = DevFileSystem::get().root_inode()->find_inode("keyboard"_sv); !ret.is_error())
keyboard_inode = ret.value().inode; keyboard_inode = ret.release_value();
else else
{ {
dprintln("could not open keyboard device: {}", ret.error()); dprintln("could not open keyboard device: {}", ret.error());

View File

@ -113,6 +113,7 @@ __BEGIN_DECLS
O(SYS_FUTEX, futex) \ O(SYS_FUTEX, futex) \
O(SYS_GETGROUPS, getgroups) \ O(SYS_GETGROUPS, getgroups) \
O(SYS_SETGROUPS, setgroups) \ O(SYS_SETGROUPS, setgroups) \
O(SYS_CHROOT, chroot) \
enum Syscall enum Syscall
{ {

View File

@ -596,6 +596,7 @@ int unlinkat(int fd, const char* path, int flag);
int usleep(useconds_t usec); int usleep(useconds_t usec);
ssize_t write(int fildes, const void* buf, size_t nbyte); ssize_t write(int fildes, const void* buf, size_t nbyte);
int chroot(const char* path);
int getpagesize(void); int getpagesize(void);
char* getpass(const char* prompt); char* getpass(const char* prompt);

View File

@ -626,6 +626,10 @@ int getopt(int argc, char* const argv[], const char* optstring)
return '?'; return '?';
} }
int chroot(const char* path)
return syscall(SYS_CHROOT, path);
}
int getpagesize(void) int getpagesize(void)
{ {
return PAGE_SIZE; return PAGE_SIZE;

View File

@ -31,7 +31,8 @@ namespace LibFont
#if __is_kernel #if __is_kernel
{ {
auto inode = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, O_RDONLY)).inode; // FIXME: This does not account for chroot
auto inode = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path(Kernel::VirtualFileSystem::get().root_inode(), { 0, 0, 0, 0 }, path, O_RDONLY)).inode;
TRY(file_data.resize(inode->size())); TRY(file_data.resize(inode->size()));
TRY(inode->read(0, BAN::ByteSpan(file_data.span()))); TRY(inode->read(0, BAN::ByteSpan(file_data.span())));
} }

View File

@ -128,7 +128,8 @@ namespace LibInput
#if __is_kernel #if __is_kernel
{ {
auto file = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, 0)); // FIXME: This does not account for chroot
auto file = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path(Kernel::VirtualFileSystem::get().root_inode(), { 0, 0, 0, 0 }, path, 0));
TRY(file_data.resize(file.inode->size())); TRY(file_data.resize(file.inode->size()));
TRY(file.inode->read(0, BAN::ByteSpan { reinterpret_cast<uint8_t*>(file_data.data()), file_data.size() })); TRY(file.inode->read(0, BAN::ByteSpan { reinterpret_cast<uint8_t*>(file_data.data()), file_data.size() }));
canonical_path = file.canonical_path; canonical_path = file.canonical_path;