mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 01:27:43 +00:00
Kernel: Make the Jails' internal design a lot more sane
This is done with 2 major steps: 1. Remove JailManagement singleton and use a structure that resembles what we have with the Process object. This is required later for the second step in this commit, but on its own, is a major change that removes this clunky singleton that had no real usage by itself. 2. Use IntrusiveLists to keep references to Process objects in the same Jail so it will be much more straightforward to iterate on this kind of objects when needed. Previously we locked the entire Process list and we did a simple pointer comparison to check if the checked Process we iterate on is in the same Jail or not, which required taking multiple Spinlocks in a very clumsy and heavyweight way.
This commit is contained in:
parent
9b297c634f
commit
633006926f
14 changed files with 214 additions and 214 deletions
|
@ -26,7 +26,6 @@
|
||||||
#include <Kernel/Devices/DeviceManagement.h>
|
#include <Kernel/Devices/DeviceManagement.h>
|
||||||
#include <Kernel/FileSystem/VirtualFileSystem.h>
|
#include <Kernel/FileSystem/VirtualFileSystem.h>
|
||||||
#include <Kernel/Graphics/Console/BootFramebufferConsole.h>
|
#include <Kernel/Graphics/Console/BootFramebufferConsole.h>
|
||||||
#include <Kernel/JailManagement.h>
|
|
||||||
#include <Kernel/KSyms.h>
|
#include <Kernel/KSyms.h>
|
||||||
#include <Kernel/Memory/MemoryManager.h>
|
#include <Kernel/Memory/MemoryManager.h>
|
||||||
#include <Kernel/Panic.h>
|
#include <Kernel/Panic.h>
|
||||||
|
@ -175,8 +174,6 @@ extern "C" [[noreturn]] void init()
|
||||||
Processor::disable_interrupts();
|
Processor::disable_interrupts();
|
||||||
TimeManagement::initialize(0);
|
TimeManagement::initialize(0);
|
||||||
|
|
||||||
JailManagement::the();
|
|
||||||
|
|
||||||
Process::initialize();
|
Process::initialize();
|
||||||
Scheduler::initialize();
|
Scheduler::initialize();
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include <Kernel/Graphics/Console/VGATextModeConsole.h>
|
#include <Kernel/Graphics/Console/VGATextModeConsole.h>
|
||||||
#include <Kernel/Graphics/GraphicsManagement.h>
|
#include <Kernel/Graphics/GraphicsManagement.h>
|
||||||
#include <Kernel/Heap/kmalloc.h>
|
#include <Kernel/Heap/kmalloc.h>
|
||||||
#include <Kernel/JailManagement.h>
|
|
||||||
#include <Kernel/KSyms.h>
|
#include <Kernel/KSyms.h>
|
||||||
#include <Kernel/Memory/MemoryManager.h>
|
#include <Kernel/Memory/MemoryManager.h>
|
||||||
#include <Kernel/Multiboot.h>
|
#include <Kernel/Multiboot.h>
|
||||||
|
@ -231,7 +230,6 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info)
|
||||||
|
|
||||||
__stack_chk_guard = get_fast_random<uintptr_t>();
|
__stack_chk_guard = get_fast_random<uintptr_t>();
|
||||||
|
|
||||||
JailManagement::the();
|
|
||||||
Process::initialize();
|
Process::initialize();
|
||||||
|
|
||||||
Scheduler::initialize();
|
Scheduler::initialize();
|
||||||
|
|
|
@ -93,7 +93,6 @@ set(KERNEL_SOURCES
|
||||||
Graphics/VirtIOGPU/GraphicsAdapter.cpp
|
Graphics/VirtIOGPU/GraphicsAdapter.cpp
|
||||||
IOWindow.cpp
|
IOWindow.cpp
|
||||||
Jail.cpp
|
Jail.cpp
|
||||||
JailManagement.cpp
|
|
||||||
SanCov.cpp
|
SanCov.cpp
|
||||||
Storage/ATA/AHCI/Controller.cpp
|
Storage/ATA/AHCI/Controller.cpp
|
||||||
Storage/ATA/AHCI/Port.cpp
|
Storage/ATA/AHCI/Port.cpp
|
||||||
|
@ -256,6 +255,7 @@ set(KERNEL_SOURCES
|
||||||
PerformanceEventBuffer.cpp
|
PerformanceEventBuffer.cpp
|
||||||
Process.cpp
|
Process.cpp
|
||||||
ProcessGroup.cpp
|
ProcessGroup.cpp
|
||||||
|
ProcessList.cpp
|
||||||
Random.cpp
|
Random.cpp
|
||||||
Scheduler.cpp
|
Scheduler.cpp
|
||||||
ScopedCritical.cpp
|
ScopedCritical.cpp
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
|
* Copyright (c) 2022-2023, Liav A. <liavalb@hotmail.co.il>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/JsonObjectSerializer.h>
|
#include <AK/JsonObjectSerializer.h>
|
||||||
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h>
|
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Jails.h>
|
||||||
#include <Kernel/JailManagement.h>
|
#include <Kernel/Jail.h>
|
||||||
#include <Kernel/Sections.h>
|
#include <Kernel/Sections.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
@ -24,7 +24,7 @@ UNMAP_AFTER_INIT NonnullLockRefPtr<SysFSJails> SysFSJails::must_create(SysFSDire
|
||||||
ErrorOr<void> SysFSJails::try_generate(KBufferBuilder& builder)
|
ErrorOr<void> SysFSJails::try_generate(KBufferBuilder& builder)
|
||||||
{
|
{
|
||||||
auto array = TRY(JsonArraySerializer<>::try_create(builder));
|
auto array = TRY(JsonArraySerializer<>::try_create(builder));
|
||||||
TRY(JailManagement::the().for_each_in_same_jail([&array](Jail& jail) -> ErrorOr<void> {
|
TRY(Jail::for_each_when_process_is_not_jailed([&array](Jail const& jail) -> ErrorOr<void> {
|
||||||
auto obj = TRY(array.add_object());
|
auto obj = TRY(array.add_object());
|
||||||
TRY(obj.add("index"sv, jail.index().value()));
|
TRY(obj.add("index"sv, jail.index().value()));
|
||||||
TRY(obj.add("name"sv, jail.name()));
|
TRY(obj.add("name"sv, jail.name()));
|
||||||
|
|
|
@ -1,21 +1,70 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
|
* Copyright (c) 2022-2023, Liav A. <liavalb@hotmail.co.il>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/IntrusiveList.h>
|
||||||
|
#include <AK/Singleton.h>
|
||||||
#include <Kernel/Jail.h>
|
#include <Kernel/Jail.h>
|
||||||
|
#include <Kernel/Process.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
ErrorOr<NonnullLockRefPtr<Jail>> Jail::create(Badge<JailManagement>, NonnullOwnPtr<KString> name, JailIndex index)
|
static Atomic<u64> s_jail_id;
|
||||||
|
static Singleton<SpinlockProtected<Jail::List, LockRank::None>> s_all_instances {};
|
||||||
|
|
||||||
|
static JailIndex generate_jail_id()
|
||||||
{
|
{
|
||||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) Jail(move(name), index));
|
return s_jail_id.fetch_add(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Jail::Jail(NonnullOwnPtr<KString> name, JailIndex index)
|
NonnullRefPtr<ProcessList> Jail::process_list()
|
||||||
|
{
|
||||||
|
return m_process_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<NonnullLockRefPtr<Jail>> Jail::create(NonnullOwnPtr<KString> name)
|
||||||
|
{
|
||||||
|
return s_all_instances->with([&](auto& list) -> ErrorOr<NonnullLockRefPtr<Jail>> {
|
||||||
|
auto process_list = TRY(ProcessList::create());
|
||||||
|
auto jail = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) Jail(move(name), generate_jail_id(), move(process_list))));
|
||||||
|
list.append(jail);
|
||||||
|
return jail;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> Jail::for_each_when_process_is_not_jailed(Function<ErrorOr<void>(Jail const&)> callback)
|
||||||
|
{
|
||||||
|
return Process::current().jail().with([&](auto const& my_jail) -> ErrorOr<void> {
|
||||||
|
// Note: If we are in a jail, don't reveal anything about the outside world,
|
||||||
|
// not even the fact that we are in which jail...
|
||||||
|
if (my_jail)
|
||||||
|
return {};
|
||||||
|
return s_all_instances->with([&](auto& list) -> ErrorOr<void> {
|
||||||
|
for (auto& jail : list) {
|
||||||
|
TRY(callback(jail));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
LockRefPtr<Jail> Jail::find_by_index(JailIndex index)
|
||||||
|
{
|
||||||
|
return s_all_instances->with([&](auto& list) -> LockRefPtr<Jail> {
|
||||||
|
for (auto& jail : list) {
|
||||||
|
if (jail.index() == index)
|
||||||
|
return jail;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Jail::Jail(NonnullOwnPtr<KString> name, JailIndex index, NonnullRefPtr<ProcessList> process_list)
|
||||||
: m_name(move(name))
|
: m_name(move(name))
|
||||||
, m_index(index)
|
, m_index(index)
|
||||||
|
, m_process_list(move(process_list))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +75,7 @@ void Jail::detach(Badge<Process>)
|
||||||
VERIFY(my_attach_count > 0);
|
VERIFY(my_attach_count > 0);
|
||||||
my_attach_count--;
|
my_attach_count--;
|
||||||
if (my_attach_count == 0) {
|
if (my_attach_count == 0) {
|
||||||
m_jail_list_node.remove();
|
m_list_node.remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
|
* Copyright (c) 2022-2023, Liav A. <liavalb@hotmail.co.il>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
#include <AK/DistinctNumeric.h>
|
#include <AK/DistinctNumeric.h>
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
#include <AK/IntrusiveList.h>
|
#include <AK/IntrusiveList.h>
|
||||||
|
#include <AK/IntrusiveListRelaxedConst.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/Try.h>
|
#include <AK/Try.h>
|
||||||
|
@ -16,19 +17,21 @@
|
||||||
#include <Kernel/KString.h>
|
#include <Kernel/KString.h>
|
||||||
#include <Kernel/Library/LockRefPtr.h>
|
#include <Kernel/Library/LockRefPtr.h>
|
||||||
#include <Kernel/Locking/SpinlockProtected.h>
|
#include <Kernel/Locking/SpinlockProtected.h>
|
||||||
#include <Kernel/Process.h>
|
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class JailManagement;
|
class ProcessList;
|
||||||
|
|
||||||
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, JailIndex);
|
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, JailIndex);
|
||||||
|
|
||||||
class Jail : public RefCounted<Jail> {
|
class Jail : public RefCounted<Jail> {
|
||||||
friend class JailManagement;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static ErrorOr<NonnullLockRefPtr<Jail>> create(Badge<JailManagement>, NonnullOwnPtr<KString>, JailIndex);
|
NonnullRefPtr<ProcessList> process_list();
|
||||||
|
|
||||||
|
static LockRefPtr<Jail> find_by_index(JailIndex);
|
||||||
|
static ErrorOr<NonnullLockRefPtr<Jail>> create(NonnullOwnPtr<KString> name);
|
||||||
|
static ErrorOr<void> for_each_when_process_is_not_jailed(Function<ErrorOr<void>(Jail const&)> callback);
|
||||||
|
|
||||||
StringView name() const { return m_name->view(); }
|
StringView name() const { return m_name->view(); }
|
||||||
JailIndex index() const { return m_index; }
|
JailIndex index() const { return m_index; }
|
||||||
|
@ -37,12 +40,19 @@ public:
|
||||||
SpinlockProtected<size_t, LockRank::None>& attach_count() { return m_attach_count; }
|
SpinlockProtected<size_t, LockRank::None>& attach_count() { return m_attach_count; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Jail(NonnullOwnPtr<KString>, JailIndex);
|
Jail(NonnullOwnPtr<KString>, JailIndex, NonnullRefPtr<ProcessList>);
|
||||||
|
|
||||||
NonnullOwnPtr<KString> m_name;
|
NonnullOwnPtr<KString> m_name;
|
||||||
JailIndex const m_index;
|
JailIndex const m_index;
|
||||||
|
|
||||||
IntrusiveListNode<Jail, NonnullLockRefPtr<Jail>> m_jail_list_node;
|
IntrusiveListNode<Jail, NonnullLockRefPtr<Jail>> m_list_node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using List = IntrusiveListRelaxedConst<&Jail::m_list_node>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NonnullRefPtr<ProcessList> m_process_list;
|
||||||
|
|
||||||
SpinlockProtected<size_t, LockRank::None> m_attach_count { 0 };
|
SpinlockProtected<size_t, LockRank::None> m_attach_count { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <AK/Singleton.h>
|
|
||||||
#include <Kernel/JailManagement.h>
|
|
||||||
#include <Kernel/Process.h>
|
|
||||||
#include <Kernel/Sections.h>
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
|
|
||||||
static Singleton<JailManagement> s_the;
|
|
||||||
static Atomic<u64> s_jail_id;
|
|
||||||
|
|
||||||
UNMAP_AFTER_INIT JailManagement::JailManagement() = default;
|
|
||||||
|
|
||||||
JailIndex JailManagement::generate_jail_id()
|
|
||||||
{
|
|
||||||
return s_jail_id.fetch_add(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
JailManagement& JailManagement::the()
|
|
||||||
{
|
|
||||||
return *s_the;
|
|
||||||
}
|
|
||||||
|
|
||||||
LockRefPtr<Jail> JailManagement::find_jail_by_index(JailIndex index)
|
|
||||||
{
|
|
||||||
return m_jails.with([&](auto& list) -> LockRefPtr<Jail> {
|
|
||||||
for (auto& jail : list) {
|
|
||||||
if (jail.index() == index)
|
|
||||||
return jail;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<void> JailManagement::for_each_in_same_jail(Function<ErrorOr<void>(Jail&)> callback)
|
|
||||||
{
|
|
||||||
return Process::current().jail().with([&](auto const& my_jail) -> ErrorOr<void> {
|
|
||||||
// Note: If we are in a jail, don't reveal anything about the outside world,
|
|
||||||
// not even the fact that we are in which jail...
|
|
||||||
if (my_jail)
|
|
||||||
return {};
|
|
||||||
return m_jails.with([&](auto& list) -> ErrorOr<void> {
|
|
||||||
for (auto& jail : list) {
|
|
||||||
TRY(callback(jail));
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
LockRefPtr<Jail> JailManagement::find_first_jail_by_name(StringView name)
|
|
||||||
{
|
|
||||||
return m_jails.with([&](auto& list) -> LockRefPtr<Jail> {
|
|
||||||
for (auto& jail : list) {
|
|
||||||
if (jail.name() == name)
|
|
||||||
return jail;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<NonnullLockRefPtr<Jail>> JailManagement::create_jail(NonnullOwnPtr<KString> name)
|
|
||||||
{
|
|
||||||
return m_jails.with([&](auto& list) -> ErrorOr<NonnullLockRefPtr<Jail>> {
|
|
||||||
auto jail = TRY(Jail::create({}, move(name), generate_jail_id()));
|
|
||||||
list.append(jail);
|
|
||||||
return jail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <AK/DistinctNumeric.h>
|
|
||||||
#include <AK/Error.h>
|
|
||||||
#include <AK/IntrusiveList.h>
|
|
||||||
#include <AK/OwnPtr.h>
|
|
||||||
#include <AK/RefPtr.h>
|
|
||||||
#include <AK/Try.h>
|
|
||||||
#include <AK/Types.h>
|
|
||||||
#include <Kernel/Jail.h>
|
|
||||||
#include <Kernel/KString.h>
|
|
||||||
#include <Kernel/Library/LockRefPtr.h>
|
|
||||||
#include <Kernel/Locking/SpinlockProtected.h>
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
|
|
||||||
class JailManagement {
|
|
||||||
|
|
||||||
public:
|
|
||||||
JailManagement();
|
|
||||||
static JailManagement& the();
|
|
||||||
|
|
||||||
LockRefPtr<Jail> find_jail_by_index(JailIndex);
|
|
||||||
LockRefPtr<Jail> find_first_jail_by_name(StringView);
|
|
||||||
|
|
||||||
ErrorOr<NonnullLockRefPtr<Jail>> create_jail(NonnullOwnPtr<KString> name);
|
|
||||||
|
|
||||||
ErrorOr<void> for_each_in_same_jail(Function<ErrorOr<void>(Jail&)>);
|
|
||||||
|
|
||||||
private:
|
|
||||||
JailIndex generate_jail_id();
|
|
||||||
|
|
||||||
SpinlockProtected<IntrusiveList<&Jail::m_jail_list_node>, LockRank::None> m_jails {};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -48,7 +48,7 @@ extern ProcessID g_init_pid;
|
||||||
|
|
||||||
RecursiveSpinlock<LockRank::None> g_profiling_lock {};
|
RecursiveSpinlock<LockRank::None> g_profiling_lock {};
|
||||||
static Atomic<pid_t> next_pid;
|
static Atomic<pid_t> next_pid;
|
||||||
static Singleton<SpinlockProtected<Process::List, LockRank::None>> s_all_instances;
|
static Singleton<SpinlockProtected<Process::AllProcessesList, LockRank::None>> s_all_instances;
|
||||||
READONLY_AFTER_INIT Memory::Region* g_signal_trampoline_region;
|
READONLY_AFTER_INIT Memory::Region* g_signal_trampoline_region;
|
||||||
|
|
||||||
static Singleton<MutexProtected<OwnPtr<KString>>> s_hostname;
|
static Singleton<MutexProtected<OwnPtr<KString>>> s_hostname;
|
||||||
|
@ -58,98 +58,89 @@ MutexProtected<OwnPtr<KString>>& hostname()
|
||||||
return *s_hostname;
|
return *s_hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpinlockProtected<Process::List, LockRank::None>& Process::all_instances()
|
SpinlockProtected<Process::AllProcessesList, LockRank::None>& Process::all_instances()
|
||||||
{
|
{
|
||||||
return *s_all_instances;
|
return *s_all_instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Process::for_each_in_same_jail(Function<ErrorOr<void>(Process&)> callback)
|
ErrorOr<void> Process::for_each_in_same_jail(Function<ErrorOr<void>(Process&)> callback)
|
||||||
{
|
{
|
||||||
ErrorOr<void> result {};
|
return Process::current().m_jail_process_list.with([&](auto const& list_ptr) -> ErrorOr<void> {
|
||||||
Process::all_instances().with([&](auto const& list) {
|
ErrorOr<void> result {};
|
||||||
Process::current().jail().with([&](auto const& my_jail) {
|
if (list_ptr) {
|
||||||
for (auto& process : list) {
|
list_ptr->attached_processes().with([&](auto const& list) {
|
||||||
if (!my_jail) {
|
for (auto& process : list) {
|
||||||
result = callback(process);
|
result = callback(process);
|
||||||
} else {
|
if (result.is_error())
|
||||||
// Note: Don't acquire the process jail spinlock twice if it's the same process
|
break;
|
||||||
// we are currently inspecting.
|
|
||||||
if (&Process::current() == &process) {
|
|
||||||
result = callback(process);
|
|
||||||
} else {
|
|
||||||
process.jail().with([&](auto const& their_jail) {
|
|
||||||
if (their_jail.ptr() == my_jail.ptr())
|
|
||||||
result = callback(process);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
all_instances().with([&](auto const& list) {
|
||||||
|
for (auto& process : list) {
|
||||||
|
result = callback(process);
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Process::for_each_child_in_same_jail(Function<ErrorOr<void>(Process&)> callback)
|
ErrorOr<void> Process::for_each_child_in_same_jail(Function<ErrorOr<void>(Process&)> callback)
|
||||||
{
|
{
|
||||||
ProcessID my_pid = pid();
|
ProcessID my_pid = pid();
|
||||||
ErrorOr<void> result {};
|
return m_jail_process_list.with([&](auto const& list_ptr) -> ErrorOr<void> {
|
||||||
Process::all_instances().with([&](auto const& list) {
|
ErrorOr<void> result {};
|
||||||
jail().with([&](auto const& my_jail) {
|
if (list_ptr) {
|
||||||
for (auto& process : list) {
|
list_ptr->attached_processes().with([&](auto const& list) {
|
||||||
if (!my_jail) {
|
for (auto& process : list) {
|
||||||
if (process.ppid() == my_pid || process.has_tracee_thread(pid()))
|
if (process.ppid() == my_pid || process.has_tracee_thread(pid()))
|
||||||
result = callback(process);
|
result = callback(process);
|
||||||
} else {
|
if (result.is_error())
|
||||||
// FIXME: Is it possible to have a child process being pointing to itself
|
break;
|
||||||
// as the parent process under normal conditions?
|
|
||||||
// Note: Don't acquire the process jail spinlock twice if it's the same process
|
|
||||||
// we are currently inspecting.
|
|
||||||
if (&Process::current() == &process && (process.ppid() == my_pid || process.has_tracee_thread(pid()))) {
|
|
||||||
result = callback(process);
|
|
||||||
} else {
|
|
||||||
process.jail().with([&](auto const& their_jail) {
|
|
||||||
if ((their_jail.ptr() == my_jail.ptr()) && (process.ppid() == my_pid || process.has_tracee_thread(pid())))
|
|
||||||
result = callback(process);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
all_instances().with([&](auto const& list) {
|
||||||
|
for (auto& process : list) {
|
||||||
|
if (process.ppid() == my_pid || process.has_tracee_thread(pid()))
|
||||||
|
result = callback(process);
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Process::for_each_in_pgrp_in_same_jail(ProcessGroupID pgid, Function<ErrorOr<void>(Process&)> callback)
|
ErrorOr<void> Process::for_each_in_pgrp_in_same_jail(ProcessGroupID pgid, Function<ErrorOr<void>(Process&)> callback)
|
||||||
{
|
{
|
||||||
ErrorOr<void> result {};
|
return m_jail_process_list.with([&](auto const& list_ptr) -> ErrorOr<void> {
|
||||||
Process::all_instances().with([&](auto const& list) {
|
ErrorOr<void> result {};
|
||||||
jail().with([&](auto const& my_jail) {
|
if (list_ptr) {
|
||||||
for (auto& process : list) {
|
list_ptr->attached_processes().with([&](auto const& list) {
|
||||||
if (!my_jail) {
|
for (auto& process : list) {
|
||||||
if (!process.is_dead() && process.pgid() == pgid)
|
if (!process.is_dead() && process.pgid() == pgid)
|
||||||
result = callback(process);
|
result = callback(process);
|
||||||
} else {
|
if (result.is_error())
|
||||||
// Note: Don't acquire the process jail spinlock twice if it's the same process
|
break;
|
||||||
// we are currently inspecting.
|
|
||||||
if (&Process::current() == &process && !process.is_dead() && process.pgid() == pgid) {
|
|
||||||
result = callback(process);
|
|
||||||
} else {
|
|
||||||
process.jail().with([&](auto const& their_jail) {
|
|
||||||
if ((their_jail.ptr() == my_jail.ptr()) && !process.is_dead() && process.pgid() == pgid)
|
|
||||||
result = callback(process);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
all_instances().with([&](auto const& list) {
|
||||||
|
for (auto& process : list) {
|
||||||
|
if (!process.is_dead() && process.pgid() == pgid)
|
||||||
|
result = callback(process);
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessID Process::allocate_pid()
|
ProcessID Process::allocate_pid()
|
||||||
|
@ -502,23 +493,21 @@ void Process::crash(int signal, Optional<RegisterState const&> regs, bool out_of
|
||||||
|
|
||||||
LockRefPtr<Process> Process::from_pid_in_same_jail(ProcessID pid)
|
LockRefPtr<Process> Process::from_pid_in_same_jail(ProcessID pid)
|
||||||
{
|
{
|
||||||
return Process::current().jail().with([&](auto const& my_jail) -> LockRefPtr<Process> {
|
return Process::current().m_jail_process_list.with([&](auto const& list_ptr) -> LockRefPtr<Process> {
|
||||||
return all_instances().with([&](auto const& list) -> LockRefPtr<Process> {
|
if (list_ptr) {
|
||||||
if (!my_jail) {
|
return list_ptr->attached_processes().with([&](auto const& list) -> LockRefPtr<Process> {
|
||||||
for (auto& process : list) {
|
for (auto& process : list) {
|
||||||
if (process.pid() == pid) {
|
if (process.pid() == pid) {
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
return {};
|
||||||
for (auto& process : list) {
|
});
|
||||||
if (process.pid() == pid) {
|
}
|
||||||
return process.jail().with([&](auto const& other_process_jail) -> LockRefPtr<Process> {
|
return all_instances().with([&](auto const& list) -> LockRefPtr<Process> {
|
||||||
if (other_process_jail.ptr() == my_jail.ptr())
|
for (auto& process : list) {
|
||||||
return process;
|
if (process.pid() == pid) {
|
||||||
return {};
|
return process;
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
@ -773,6 +762,13 @@ void Process::finalize()
|
||||||
m_fds.with_exclusive([](auto& fds) { fds.clear(); });
|
m_fds.with_exclusive([](auto& fds) { fds.clear(); });
|
||||||
m_tty = nullptr;
|
m_tty = nullptr;
|
||||||
m_executable.with([](auto& executable) { executable = nullptr; });
|
m_executable.with([](auto& executable) { executable = nullptr; });
|
||||||
|
m_jail_process_list.with([this](auto& list_ptr) {
|
||||||
|
if (list_ptr) {
|
||||||
|
list_ptr->attached_processes().with([&](auto& list) {
|
||||||
|
list.remove(*this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
m_attached_jail.with([](auto& jail) {
|
m_attached_jail.with([](auto& jail) {
|
||||||
if (jail)
|
if (jail)
|
||||||
jail->detach({});
|
jail->detach({});
|
||||||
|
|
|
@ -104,6 +104,8 @@ static_assert(sizeof(GlobalFutexKey) == (sizeof(FlatPtr) * 2));
|
||||||
|
|
||||||
struct LoadResult;
|
struct LoadResult;
|
||||||
|
|
||||||
|
class ProcessList;
|
||||||
|
|
||||||
class Process final
|
class Process final
|
||||||
: public ListedRefCounted<Process, LockType::Spinlock>
|
: public ListedRefCounted<Process, LockType::Spinlock>
|
||||||
, public LockWeakable<Process> {
|
, public LockWeakable<Process> {
|
||||||
|
@ -665,8 +667,6 @@ private:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveListNode<Process> m_list_node;
|
|
||||||
|
|
||||||
SpinlockProtected<NonnullOwnPtr<KString>, LockRank::None> m_name;
|
SpinlockProtected<NonnullOwnPtr<KString>, LockRank::None> m_name;
|
||||||
|
|
||||||
SpinlockProtected<OwnPtr<Memory::AddressSpace>, LockRank::None> m_space;
|
SpinlockProtected<OwnPtr<Memory::AddressSpace>, LockRank::None> m_space;
|
||||||
|
@ -852,7 +852,15 @@ private:
|
||||||
|
|
||||||
LockWeakPtr<Memory::Region> m_master_tls_region;
|
LockWeakPtr<Memory::Region> m_master_tls_region;
|
||||||
|
|
||||||
IntrusiveListNode<Process> m_jail_list_node;
|
IntrusiveListNode<Process> m_jail_process_list_node;
|
||||||
|
IntrusiveListNode<Process> m_all_processes_list_node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using AllProcessesList = IntrusiveListRelaxedConst<&Process::m_all_processes_list_node>;
|
||||||
|
using JailProcessList = IntrusiveListRelaxedConst<&Process::m_jail_process_list_node>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpinlockProtected<RefPtr<ProcessList>, LockRank::None> m_jail_process_list;
|
||||||
SpinlockProtected<RefPtr<Jail>, LockRank::Process> m_attached_jail {};
|
SpinlockProtected<RefPtr<Jail>, LockRank::Process> m_attached_jail {};
|
||||||
|
|
||||||
size_t m_master_tls_size { 0 };
|
size_t m_master_tls_size { 0 };
|
||||||
|
@ -895,8 +903,18 @@ private:
|
||||||
u8 m_protected_values_padding[PAGE_SIZE - sizeof(ProtectedValues)];
|
u8 m_protected_values_padding[PAGE_SIZE - sizeof(ProtectedValues)];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using List = IntrusiveListRelaxedConst<&Process::m_list_node>;
|
static SpinlockProtected<Process::AllProcessesList, LockRank::None>& all_instances();
|
||||||
static SpinlockProtected<Process::List, LockRank::None>& all_instances();
|
};
|
||||||
|
|
||||||
|
class ProcessList : public RefCounted<ProcessList> {
|
||||||
|
public:
|
||||||
|
static ErrorOr<NonnullRefPtr<ProcessList>> create();
|
||||||
|
SpinlockProtected<Process::JailProcessList, LockRank::None>& attached_processes() { return m_attached_processes; }
|
||||||
|
SpinlockProtected<Process::JailProcessList, LockRank::None> const& attached_processes() const { return m_attached_processes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProcessList() = default;
|
||||||
|
SpinlockProtected<Process::JailProcessList, LockRank::None> m_attached_processes;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note: Process object should be 2 pages of 4096 bytes each.
|
// Note: Process object should be 2 pages of 4096 bytes each.
|
||||||
|
|
16
Kernel/ProcessList.cpp
Normal file
16
Kernel/ProcessList.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Kernel/Process.h>
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
ErrorOr<NonnullRefPtr<ProcessList>> ProcessList::create()
|
||||||
|
{
|
||||||
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcessList());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -516,6 +516,7 @@ ErrorOr<void> Process::do_exec(NonnullRefPtr<OpenFileDescription> main_program_d
|
||||||
auto old_credentials = this->credentials();
|
auto old_credentials = this->credentials();
|
||||||
auto new_credentials = old_credentials;
|
auto new_credentials = old_credentials;
|
||||||
auto old_process_attached_jail = m_attached_jail.with([&](auto& jail) -> RefPtr<Jail> { return jail; });
|
auto old_process_attached_jail = m_attached_jail.with([&](auto& jail) -> RefPtr<Jail> { return jail; });
|
||||||
|
auto old_scoped_list = m_jail_process_list.with([&](auto& list) -> RefPtr<ProcessList> { return list; });
|
||||||
|
|
||||||
bool executable_is_setid = false;
|
bool executable_is_setid = false;
|
||||||
|
|
||||||
|
@ -578,6 +579,11 @@ ErrorOr<void> Process::do_exec(NonnullRefPtr<OpenFileDescription> main_program_d
|
||||||
m_attached_jail.with([&](auto& jail) {
|
m_attached_jail.with([&](auto& jail) {
|
||||||
jail = old_process_attached_jail;
|
jail = old_process_attached_jail;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_jail_process_list.with([&](auto& list) {
|
||||||
|
list = old_scoped_list;
|
||||||
|
});
|
||||||
|
|
||||||
m_environment = move(environment);
|
m_environment = move(environment);
|
||||||
|
|
||||||
TRY(m_unveil_data.with([&](auto& unveil_data) -> ErrorOr<void> {
|
TRY(m_unveil_data.with([&](auto& unveil_data) -> ErrorOr<void> {
|
||||||
|
|
|
@ -70,6 +70,26 @@ ErrorOr<FlatPtr> Process::sys$fork(RegisterState& regs)
|
||||||
return {};
|
return {};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
ArmedScopeGuard remove_from_jail_process_list = [&]() {
|
||||||
|
m_jail_process_list.with([&](auto& list_ptr) {
|
||||||
|
if (list_ptr) {
|
||||||
|
list_ptr->attached_processes().with([&](auto& list) {
|
||||||
|
list.remove(*child);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
m_jail_process_list.with([&](auto& list_ptr) {
|
||||||
|
if (list_ptr) {
|
||||||
|
child->m_jail_process_list.with([&](auto& child_list_ptr) {
|
||||||
|
child_list_ptr = list_ptr;
|
||||||
|
});
|
||||||
|
list_ptr->attached_processes().with([&](auto& list) {
|
||||||
|
list.append(child);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
TRY(child->m_fds.with_exclusive([&](auto& child_fds) {
|
TRY(child->m_fds.with_exclusive([&](auto& child_fds) {
|
||||||
return m_fds.with_exclusive([&](auto& parent_fds) {
|
return m_fds.with_exclusive([&](auto& parent_fds) {
|
||||||
return child_fds.try_clone(parent_fds);
|
return child_fds.try_clone(parent_fds);
|
||||||
|
@ -150,6 +170,7 @@ ErrorOr<FlatPtr> Process::sys$fork(RegisterState& regs)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
thread_finalizer_guard.disarm();
|
thread_finalizer_guard.disarm();
|
||||||
|
remove_from_jail_process_list.disarm();
|
||||||
|
|
||||||
Process::register_new(*child);
|
Process::register_new(*child);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <AK/Userspace.h>
|
#include <AK/Userspace.h>
|
||||||
#include <Kernel/API/Ioctl.h>
|
#include <Kernel/API/Ioctl.h>
|
||||||
#include <Kernel/Jail.h>
|
#include <Kernel/Jail.h>
|
||||||
#include <Kernel/JailManagement.h>
|
|
||||||
#include <Kernel/Process.h>
|
#include <Kernel/Process.h>
|
||||||
#include <Kernel/StdLib.h>
|
#include <Kernel/StdLib.h>
|
||||||
|
|
||||||
|
@ -31,7 +30,7 @@ ErrorOr<FlatPtr> Process::sys$jail_create(Userspace<Syscall::SC_jail_create_para
|
||||||
// any info leak about the "outside world" jail metadata.
|
// any info leak about the "outside world" jail metadata.
|
||||||
if (my_jail)
|
if (my_jail)
|
||||||
return Error::from_errno(EPERM);
|
return Error::from_errno(EPERM);
|
||||||
auto jail = TRY(JailManagement::the().create_jail(move(jail_name)));
|
auto jail = TRY(Jail::create(move(jail_name)));
|
||||||
return jail->index().value();
|
return jail->index().value();
|
||||||
}));
|
}));
|
||||||
// Note: We do the copy_to_user outside of the m_attached_jail Spinlock locked scope because
|
// Note: We do the copy_to_user outside of the m_attached_jail Spinlock locked scope because
|
||||||
|
@ -64,13 +63,21 @@ ErrorOr<FlatPtr> Process::sys$jail_attach(Userspace<Syscall::SC_jail_attach_para
|
||||||
// in the system, just return EPERM before doing anything else.
|
// in the system, just return EPERM before doing anything else.
|
||||||
if (my_jail)
|
if (my_jail)
|
||||||
return EPERM;
|
return EPERM;
|
||||||
auto jail = JailManagement::the().find_jail_by_index(static_cast<JailIndex>(params.index));
|
auto jail = Jail::find_by_index(static_cast<JailIndex>(params.index));
|
||||||
if (!jail)
|
if (!jail)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
my_jail = *jail;
|
my_jail = *jail;
|
||||||
my_jail->attach_count().with([&](auto& attach_count) {
|
my_jail->attach_count().with([&](auto& attach_count) {
|
||||||
attach_count++;
|
attach_count++;
|
||||||
});
|
});
|
||||||
|
m_jail_process_list.with([&](auto& list_ptr) {
|
||||||
|
list_ptr = my_jail->process_list();
|
||||||
|
if (list_ptr) {
|
||||||
|
list_ptr->attached_processes().with([&](auto& list) {
|
||||||
|
list.append(*this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue