mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:17:44 +00:00
Kernel: Guard Process "protected data" with a spinlock
This ensures that both mutable and immutable access to the protected data of a process is serialized. Note that there may still be multiple TOCTOU issues around this, as we have a bunch of convenience accessors that make it easy to introduce them. We'll need to audit those as well.
This commit is contained in:
parent
728c3fbd14
commit
8ed06ad814
11 changed files with 348 additions and 300 deletions
|
@ -135,20 +135,19 @@ public:
|
|||
friend class Thread;
|
||||
friend class Coredump;
|
||||
|
||||
// Helper class to temporarily unprotect a process's protected data so you can write to it.
|
||||
class ProtectedDataMutationScope {
|
||||
public:
|
||||
explicit ProtectedDataMutationScope(Process& process)
|
||||
: m_process(process)
|
||||
{
|
||||
m_process.unprotect_data();
|
||||
}
|
||||
auto with_protected_data(auto&& callback) const
|
||||
{
|
||||
SpinlockLocker locker(m_protected_data_lock);
|
||||
return callback(m_protected_values_do_not_access_directly);
|
||||
}
|
||||
|
||||
~ProtectedDataMutationScope() { m_process.protect_data(); }
|
||||
|
||||
private:
|
||||
Process& m_process;
|
||||
};
|
||||
auto with_mutable_protected_data(auto&& callback)
|
||||
{
|
||||
SpinlockLocker locker(m_protected_data_lock);
|
||||
unprotect_data();
|
||||
auto guard = ScopeGuard([&] { protect_data(); });
|
||||
return callback(m_protected_values_do_not_access_directly);
|
||||
}
|
||||
|
||||
enum class State : u8 {
|
||||
Running = 0,
|
||||
|
@ -218,12 +217,21 @@ public:
|
|||
static SessionID get_sid_from_pgid(ProcessGroupID pgid);
|
||||
|
||||
StringView name() const { return m_name->view(); }
|
||||
ProcessID pid() const { return m_protected_values.pid; }
|
||||
SessionID sid() const { return m_protected_values.sid; }
|
||||
ProcessID pid() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.pid; });
|
||||
}
|
||||
SessionID sid() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.sid; });
|
||||
}
|
||||
bool is_session_leader() const { return sid().value() == pid().value(); }
|
||||
ProcessGroupID pgid() const { return m_pg ? m_pg->pgid() : 0; }
|
||||
bool is_group_leader() const { return pgid().value() == pid().value(); }
|
||||
ProcessID ppid() const { return m_protected_values.ppid; }
|
||||
ProcessID ppid() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.ppid; });
|
||||
}
|
||||
|
||||
NonnullRefPtr<Credentials> credentials() const;
|
||||
|
||||
|
@ -234,10 +242,16 @@ public:
|
|||
UserID suid() const;
|
||||
GroupID sgid() const;
|
||||
|
||||
bool is_dumpable() const { return m_protected_values.dumpable; }
|
||||
bool is_dumpable() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.dumpable; });
|
||||
}
|
||||
void set_dumpable(bool);
|
||||
|
||||
mode_t umask() const { return m_protected_values.umask; }
|
||||
mode_t umask() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.umask; });
|
||||
}
|
||||
|
||||
bool in_group(GroupID) const;
|
||||
|
||||
|
@ -467,19 +481,37 @@ public:
|
|||
void terminate_due_to_signal(u8 signal);
|
||||
ErrorOr<void> send_signal(u8 signal, Process* sender);
|
||||
|
||||
u8 termination_signal() const { return m_protected_values.termination_signal; }
|
||||
u8 termination_status() const { return m_protected_values.termination_status; }
|
||||
u8 termination_signal() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) -> u8 {
|
||||
return protected_data.termination_signal;
|
||||
});
|
||||
}
|
||||
u8 termination_status() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.termination_status; });
|
||||
}
|
||||
|
||||
u16 thread_count() const
|
||||
{
|
||||
return m_protected_values.thread_count.load(AK::MemoryOrder::memory_order_relaxed);
|
||||
return with_protected_data([](auto& protected_data) {
|
||||
return protected_data.thread_count.load(AK::MemoryOrder::memory_order_relaxed);
|
||||
});
|
||||
}
|
||||
|
||||
Mutex& big_lock() { return m_big_lock; }
|
||||
Mutex& ptrace_lock() { return m_ptrace_lock; }
|
||||
|
||||
bool has_promises() const { return m_protected_values.has_promises; }
|
||||
bool has_promised(Pledge pledge) const { return (m_protected_values.promises & (1U << (u32)pledge)) != 0; }
|
||||
bool has_promises() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.has_promises.load(); });
|
||||
}
|
||||
bool has_promised(Pledge pledge) const
|
||||
{
|
||||
return with_protected_data([&](auto& protected_data) {
|
||||
return (protected_data.promises & (1U << (u32)pledge)) != 0;
|
||||
});
|
||||
}
|
||||
|
||||
VeilState veil_state() const
|
||||
{
|
||||
|
@ -539,7 +571,10 @@ public:
|
|||
Memory::AddressSpace& address_space() { return *m_space; }
|
||||
Memory::AddressSpace const& address_space() const { return *m_space; }
|
||||
|
||||
VirtualAddress signal_trampoline() const { return m_protected_values.signal_trampoline; }
|
||||
VirtualAddress signal_trampoline() const
|
||||
{
|
||||
return with_protected_data([](auto& protected_data) { return protected_data.signal_trampoline; });
|
||||
}
|
||||
|
||||
ErrorOr<void> require_promise(Pledge);
|
||||
ErrorOr<void> require_no_promises() const;
|
||||
|
@ -635,6 +670,7 @@ private:
|
|||
|
||||
LockRefPtr<ProcessGroup> m_pg;
|
||||
|
||||
RecursiveSpinlock mutable m_protected_data_lock;
|
||||
AtomicEdgeAction<u32> m_protected_data_refs;
|
||||
void protect_data();
|
||||
void unprotect_data();
|
||||
|
@ -870,7 +906,7 @@ private:
|
|||
Array<SignalActionData, NSIG> m_signal_action_data;
|
||||
|
||||
static_assert(sizeof(ProtectedValues) < (PAGE_SIZE));
|
||||
alignas(4096) ProtectedValues m_protected_values;
|
||||
alignas(4096) ProtectedValues m_protected_values_do_not_access_directly;
|
||||
u8 m_protected_values_padding[PAGE_SIZE - sizeof(ProtectedValues)];
|
||||
|
||||
public:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue