summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2022-11-02 22:26:02 +0200
committerAndrew Kaster <andrewdkaster@gmail.com>2022-11-05 18:00:58 -0600
commit5e062414c11df31ed595c363990005eef00fa263 (patch)
tree62281b52f5408e4b3b814553e9cf18a234cc001e /Kernel/FileSystem
parentd69a0380e1558e82a6a0bda71e66eab121cdcda4 (diff)
downloadserenity-5e062414c11df31ed595c363990005eef00fa263.zip
Kernel: Add support for jails
Our implementation for Jails resembles much of how FreeBSD jails are working - it's essentially only a matter of using a RefPtr in the Process class to a Jail object. Then, when we iterate over all processes in various cases, we could ensure if either the current process is in jail and therefore should be restricted what is visible in terms of PID isolation, and also to be able to expose metadata about Jails in /sys/kernel/jails node (which does not reveal anything to a process which is in jail). A lifetime model for the Jail object is currently plain simple - there's simpy no way to manually delete a Jail object once it was created. Such feature should be carefully designed to allow safe destruction of a Jail without the possibility of releasing a process which is in Jail from the actual jail. Each process which is attached into a Jail cannot leave it until the end of a Process (i.e. when finalizing a Process). All jails are kept being referenced in the JailManagement. When a last attached process is finalized, the Jail is automatically destroyed.
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r--Kernel/FileSystem/ProcFS.cpp18
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Directory.cpp2
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.cpp38
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h28
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp6
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.cpp27
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.cpp4
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.h3
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.cpp4
-rw-r--r--Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.h3
10 files changed, 106 insertions, 27 deletions
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp
index 214e7d00b5..6eb4ad3771 100644
--- a/Kernel/FileSystem/ProcFS.cpp
+++ b/Kernel/FileSystem/ProcFS.cpp
@@ -256,7 +256,7 @@ ErrorOr<void> ProcFSProcessDirectoryInode::attach(OpenFileDescription&)
InodeMetadata ProcFSProcessDirectoryInode::metadata() const
{
MutexLocker locker(m_inode_lock);
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return {};
@@ -279,7 +279,7 @@ ErrorOr<size_t> ProcFSProcessDirectoryInode::read_bytes_locked(off_t, size_t, Us
ErrorOr<void> ProcFSProcessDirectoryInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
{
MutexLocker locker(procfs().m_lock);
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return EINVAL;
return process->procfs_traits()->traverse_as_directory(procfs().fsid(), move(callback));
@@ -288,7 +288,7 @@ ErrorOr<void> ProcFSProcessDirectoryInode::traverse_as_directory(Function<ErrorO
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSProcessDirectoryInode::lookup(StringView name)
{
MutexLocker locker(procfs().m_lock);
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return ESRCH;
if (name == "fd"sv)
@@ -345,7 +345,7 @@ void ProcFSProcessSubDirectoryInode::did_seek(OpenFileDescription&, off_t)
InodeMetadata ProcFSProcessSubDirectoryInode::metadata() const
{
MutexLocker locker(m_inode_lock);
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return {};
@@ -363,7 +363,7 @@ InodeMetadata ProcFSProcessSubDirectoryInode::metadata() const
ErrorOr<void> ProcFSProcessSubDirectoryInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
{
MutexLocker locker(procfs().m_lock);
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return EINVAL;
switch (m_sub_directory_type) {
@@ -382,7 +382,7 @@ ErrorOr<void> ProcFSProcessSubDirectoryInode::traverse_as_directory(Function<Err
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSProcessSubDirectoryInode::lookup(StringView name)
{
MutexLocker locker(procfs().m_lock);
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return ESRCH;
switch (m_sub_directory_type) {
@@ -472,7 +472,7 @@ static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessS
InodeMetadata ProcFSProcessPropertyInode::metadata() const
{
MutexLocker locker(m_inode_lock);
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return {};
@@ -499,7 +499,7 @@ ErrorOr<size_t> ProcFSProcessPropertyInode::read_bytes_locked(off_t offset, size
if (!description) {
auto builder = TRY(KBufferBuilder::try_create());
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return Error::from_errno(ESRCH);
TRY(try_to_acquire_data(*process, builder));
@@ -585,7 +585,7 @@ ErrorOr<void> ProcFSProcessPropertyInode::refresh_data(OpenFileDescription& desc
// For process-specific inodes, hold the process's ptrace lock across refresh
// and refuse to load data if the process is not dumpable.
// Without this, files opened before a process went non-dumpable could still be used for dumping.
- auto process = Process::from_pid(associated_pid());
+ auto process = Process::from_pid_in_same_jail(associated_pid());
if (!process)
return Error::from_errno(ESRCH);
process->ptrace_lock().lock();
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Directory.cpp b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Directory.cpp
index 18980243b0..469f7d3fb5 100644
--- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Directory.cpp
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Directory.cpp
@@ -13,6 +13,7 @@
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/DiskUsage.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/GlobalInformation.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Interrupts.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Keymap.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/LoadBase.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Log.h>
@@ -46,6 +47,7 @@ UNMAP_AFTER_INIT NonnullLockRefPtr<SysFSGlobalKernelStatsDirectory> SysFSGlobalK
list.append(SysFSProfile::must_create(*global_kernel_stats_directory));
list.append(SysFSKernelLoadBase::must_create(*global_kernel_stats_directory));
list.append(SysFSPowerStateSwitchNode::must_create(*global_kernel_stats_directory));
+ list.append(SysFSJails::must_create(*global_kernel_stats_directory));
list.append(SysFSGlobalNetworkStatsDirectory::must_create(*global_kernel_stats_directory));
list.append(SysFSGlobalKernelVariablesDirectory::must_create(*global_kernel_stats_directory));
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.cpp b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.cpp
new file mode 100644
index 0000000000..dbe37ce092
--- /dev/null
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/JsonObjectSerializer.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h>
+#include <Kernel/JailManagement.h>
+#include <Kernel/Sections.h>
+
+namespace Kernel {
+
+UNMAP_AFTER_INIT SysFSJails::SysFSJails(SysFSDirectory const& parent_directory)
+ : SysFSGlobalInformation(parent_directory)
+{
+}
+
+UNMAP_AFTER_INIT NonnullLockRefPtr<SysFSJails> SysFSJails::must_create(SysFSDirectory const& parent_directory)
+{
+ return adopt_lock_ref_if_nonnull(new (nothrow) SysFSJails(parent_directory)).release_nonnull();
+}
+
+ErrorOr<void> SysFSJails::try_generate(KBufferBuilder& builder)
+{
+ auto array = TRY(JsonArraySerializer<>::try_create(builder));
+ TRY(JailManagement::the().for_each_in_same_jail([&array](Jail& jail) -> ErrorOr<void> {
+ auto obj = TRY(array.add_object());
+ TRY(obj.add("index"sv, jail.index().value()));
+ TRY(obj.add("name"sv, jail.name()));
+ TRY(obj.finish());
+ return {};
+ }));
+ TRY(array.finish());
+ return {};
+}
+
+}
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h
new file mode 100644
index 0000000000..2dfbf73eaa
--- /dev/null
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/GlobalInformation.h>
+#include <Kernel/KBufferBuilder.h>
+#include <Kernel/Library/LockRefPtr.h>
+#include <Kernel/UserOrKernelBuffer.h>
+
+namespace Kernel {
+
+class SysFSJails final : public SysFSGlobalInformation {
+public:
+ virtual StringView name() const override { return "jails"sv; }
+
+ static NonnullLockRefPtr<SysFSJails> must_create(SysFSDirectory const& parent_directory);
+
+private:
+ explicit SysFSJails(SysFSDirectory const& parent_directory);
+ virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override;
+};
+
+}
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp
index d9ba50c8fb..50ddbf3b18 100644
--- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp
@@ -141,10 +141,10 @@ ErrorOr<void> SysFSOverallProcesses::try_generate(KBufferBuilder& builder)
{
auto array = TRY(json.add_array("processes"sv));
+ // FIXME: Do we actually want to expose the colonel process in a Jail environment?
TRY(build_process(array, *Scheduler::colonel()));
- TRY(Process::all_instances().with([&](auto& processes) -> ErrorOr<void> {
- for (auto& process : processes)
- TRY(build_process(array, process));
+ TRY(Process::for_each_in_same_jail([&](Process& process) -> ErrorOr<void> {
+ TRY(build_process(array, process));
return {};
}));
TRY(array.finish());
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.cpp b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.cpp
index e1a1b43486..456f07480d 100644
--- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.cpp
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.cpp
@@ -5,6 +5,7 @@
*/
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.h>
+#include <Kernel/Process.h>
#include <Kernel/Sections.h>
namespace Kernel {
@@ -16,18 +17,26 @@ ErrorOr<void> SysFSSystemBoolean::try_generate(KBufferBuilder& builder)
ErrorOr<size_t> SysFSSystemBoolean::write_bytes(off_t, size_t count, UserOrKernelBuffer const& buffer, OpenFileDescription*)
{
- if (count != 1)
- return EINVAL;
MutexLocker locker(m_refresh_lock);
+ // Note: We do all of this code before taking the spinlock because then we disable
+ // interrupts so page faults will not work.
char value = 0;
TRY(buffer.read(&value, 1));
- if (value == '0')
- set_value(false);
- else if (value == '1')
- set_value(true);
- else
- return EINVAL;
- return 1;
+
+ return Process::current().jail().with([&](auto& my_jail) -> ErrorOr<size_t> {
+ // Note: If we are in a jail, don't let the current process to change the variable.
+ if (my_jail)
+ return Error::from_errno(EPERM);
+ if (count != 1)
+ return Error::from_errno(EINVAL);
+ if (value == '0')
+ set_value(false);
+ else if (value == '1')
+ set_value(true);
+ else
+ return Error::from_errno(EINVAL);
+ return 1;
+ });
}
ErrorOr<void> SysFSSystemBoolean::truncate(u64 size)
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.cpp b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.cpp
index eec99b37a1..1c74621224 100644
--- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.cpp
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.cpp
@@ -22,12 +22,12 @@ UNMAP_AFTER_INIT NonnullLockRefPtr<SysFSCapsLockRemap> SysFSCapsLockRemap::must_
bool SysFSCapsLockRemap::value() const
{
- MutexLocker locker(m_lock);
+ SpinlockLocker locker(m_lock);
return g_caps_lock_remapped_to_ctrl.load();
}
void SysFSCapsLockRemap::set_value(bool new_value)
{
- MutexLocker locker(m_lock);
+ SpinlockLocker locker(m_lock);
g_caps_lock_remapped_to_ctrl.exchange(new_value);
}
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.h b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.h
index 3cb0390bd0..effbcd6e49 100644
--- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.h
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/CapsLockRemap.h
@@ -9,6 +9,7 @@
#include <AK/Types.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.h>
#include <Kernel/Library/LockRefPtr.h>
+#include <Kernel/Locking/Spinlock.h>
#include <Kernel/UserOrKernelBuffer.h>
namespace Kernel {
@@ -24,7 +25,7 @@ private:
explicit SysFSCapsLockRemap(SysFSDirectory const&);
- mutable Mutex m_lock;
+ mutable Spinlock m_lock { LockRank::None };
};
}
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.cpp b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.cpp
index f1645a1c8e..5464b6ac77 100644
--- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.cpp
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.cpp
@@ -22,13 +22,13 @@ UNMAP_AFTER_INIT NonnullLockRefPtr<SysFSDumpKmallocStacks> SysFSDumpKmallocStack
bool SysFSDumpKmallocStacks::value() const
{
- MutexLocker locker(m_lock);
+ SpinlockLocker locker(m_lock);
return g_dump_kmalloc_stacks;
}
void SysFSDumpKmallocStacks::set_value(bool new_value)
{
- MutexLocker locker(m_lock);
+ SpinlockLocker locker(m_lock);
g_dump_kmalloc_stacks = new_value;
}
diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.h b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.h
index 21719e22f4..7e29ac3385 100644
--- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.h
+++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/DumpKmallocStack.h
@@ -9,6 +9,7 @@
#include <AK/Types.h>
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Variables/BooleanVariable.h>
#include <Kernel/Library/LockRefPtr.h>
+#include <Kernel/Locking/Spinlock.h>
#include <Kernel/UserOrKernelBuffer.h>
namespace Kernel {
@@ -24,7 +25,7 @@ private:
explicit SysFSDumpKmallocStacks(SysFSDirectory const&);
- mutable Mutex m_lock;
+ mutable Spinlock m_lock { LockRank::None };
};
}