mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 05:28:11 +00:00
Kernel: Add jail semantics to methods iterating over thread lists
We should consider whether the selected Thread is within the same jail or not. Therefore let's make it clear to callers with jail semantics if a called method checks if the desired Thread object is within the same jail. As for Thread::for_each_* methods, currently nothing in the kernel codebase needs iteration with consideration for jails, so the old Thread::for_each* were simply renamed to include "ignoring_jails" suffix in their names.
This commit is contained in:
parent
3a55a1b592
commit
cbaa3465a8
7 changed files with 36 additions and 17 deletions
|
@ -41,7 +41,7 @@ ErrorOr<NonnullRefPtr<Inode>> Process::lookup_as_directory(ProcFS& procfs, Strin
|
||||||
ErrorOr<void> Process::procfs_get_thread_stack(ThreadID thread_id, KBufferBuilder& builder) const
|
ErrorOr<void> Process::procfs_get_thread_stack(ThreadID thread_id, KBufferBuilder& builder) const
|
||||||
{
|
{
|
||||||
auto array = TRY(JsonArraySerializer<>::try_create(builder));
|
auto array = TRY(JsonArraySerializer<>::try_create(builder));
|
||||||
auto thread = Thread::from_tid(thread_id);
|
auto thread = Thread::from_tid_in_same_jail(thread_id);
|
||||||
if (!thread)
|
if (!thread)
|
||||||
return ESRCH;
|
return ESRCH;
|
||||||
auto current_process_credentials = Process::current().credentials();
|
auto current_process_credentials = Process::current().credentials();
|
||||||
|
|
|
@ -34,7 +34,7 @@ static ErrorOr<FlatPtr> handle_ptrace(Kernel::Syscall::SC_ptrace_params const& p
|
||||||
if (params.tid == caller.pid().value())
|
if (params.tid == caller.pid().value())
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
auto peer = Thread::from_tid(params.tid);
|
auto peer = Thread::from_tid_in_same_jail(params.tid);
|
||||||
if (!peer)
|
if (!peer)
|
||||||
return ESRCH;
|
return ESRCH;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ ErrorOr<NonnullRefPtr<Thread>> Process::get_thread_from_pid_or_tid(pid_t pid_or_
|
||||||
case Syscall::SchedulerParametersMode::Thread: {
|
case Syscall::SchedulerParametersMode::Thread: {
|
||||||
peer = Thread::current();
|
peer = Thread::current();
|
||||||
if (pid_or_tid != 0)
|
if (pid_or_tid != 0)
|
||||||
peer = Thread::from_tid(pid_or_tid);
|
peer = Thread::from_tid_in_same_jail(pid_or_tid);
|
||||||
|
|
||||||
// Only superuser can access other processes' threads.
|
// Only superuser can access other processes' threads.
|
||||||
if (!credentials()->is_superuser() && peer && &peer->process() != this)
|
if (!credentials()->is_superuser() && peer && &peer->process() != this)
|
||||||
|
|
|
@ -952,7 +952,7 @@ ErrorOr<void> Process::send_signal(u8 signal, Process* sender)
|
||||||
{
|
{
|
||||||
VERIFY(is_user_process());
|
VERIFY(is_user_process());
|
||||||
// Try to send it to the "obvious" main thread:
|
// Try to send it to the "obvious" main thread:
|
||||||
auto receiver_thread = Thread::from_tid(pid().value());
|
auto receiver_thread = Thread::from_tid_in_same_jail(pid().value());
|
||||||
// If the main thread has died, there may still be other threads:
|
// If the main thread has died, there may still be other threads:
|
||||||
if (!receiver_thread) {
|
if (!receiver_thread) {
|
||||||
// The first one should be good enough.
|
// The first one should be good enough.
|
||||||
|
|
|
@ -513,7 +513,7 @@ void dump_thread_list(bool with_stack_traces)
|
||||||
return thread.get_register_dump_from_stack().ip();
|
return thread.get_register_dump_from_stack().ip();
|
||||||
};
|
};
|
||||||
|
|
||||||
Thread::for_each([&](Thread& thread) {
|
Thread::for_each_ignoring_jails([&](Thread& thread) {
|
||||||
auto color = thread.process().is_kernel_process() ? "\x1b[34;1m"sv : "\x1b[33;1m"sv;
|
auto color = thread.process().is_kernel_process() ? "\x1b[34;1m"sv : "\x1b[33;1m"sv;
|
||||||
switch (thread.state()) {
|
switch (thread.state()) {
|
||||||
case Thread::State::Dying:
|
case Thread::State::Dying:
|
||||||
|
|
|
@ -589,7 +589,7 @@ void Thread::finalize_dying_threads()
|
||||||
Vector<Thread*, 32> dying_threads;
|
Vector<Thread*, 32> dying_threads;
|
||||||
{
|
{
|
||||||
SpinlockLocker lock(g_scheduler_lock);
|
SpinlockLocker lock(g_scheduler_lock);
|
||||||
for_each_in_state(Thread::State::Dying, [&](Thread& thread) {
|
for_each_in_state_ignoring_jails(Thread::State::Dying, [&](Thread& thread) {
|
||||||
if (!thread.is_finalizable())
|
if (!thread.is_finalizable())
|
||||||
return;
|
return;
|
||||||
auto result = dying_threads.try_append(&thread);
|
auto result = dying_threads.try_append(&thread);
|
||||||
|
@ -1398,7 +1398,25 @@ ErrorOr<void> Thread::make_thread_specific_region(Badge<Process>)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Thread> Thread::from_tid(ThreadID tid)
|
RefPtr<Thread> Thread::from_tid_in_same_jail(ThreadID tid)
|
||||||
|
{
|
||||||
|
return Thread::all_instances().with([&](auto& list) -> RefPtr<Thread> {
|
||||||
|
for (Thread& thread : list) {
|
||||||
|
if (thread.tid() == tid) {
|
||||||
|
return Process::current().jail().with([&thread](auto const& my_jail) -> RefPtr<Thread> {
|
||||||
|
return thread.process().jail().with([&thread, my_jail](auto const& other_thread_process_jail) -> RefPtr<Thread> {
|
||||||
|
if (my_jail && my_jail.ptr() != other_thread_process_jail.ptr())
|
||||||
|
return nullptr;
|
||||||
|
return thread;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Thread> Thread::from_tid_ignoring_jails(ThreadID tid)
|
||||||
{
|
{
|
||||||
return Thread::all_instances().with([&](auto& list) -> RefPtr<Thread> {
|
return Thread::all_instances().with([&](auto& list) -> RefPtr<Thread> {
|
||||||
for (Thread& thread : list) {
|
for (Thread& thread : list) {
|
||||||
|
|
|
@ -71,7 +71,8 @@ public:
|
||||||
static ErrorOr<NonnullRefPtr<Thread>> create(NonnullRefPtr<Process>);
|
static ErrorOr<NonnullRefPtr<Thread>> create(NonnullRefPtr<Process>);
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|
||||||
static RefPtr<Thread> from_tid(ThreadID);
|
static RefPtr<Thread> from_tid_ignoring_jails(ThreadID);
|
||||||
|
static RefPtr<Thread> from_tid_in_same_jail(ThreadID);
|
||||||
static void finalize_dying_threads();
|
static void finalize_dying_threads();
|
||||||
|
|
||||||
ThreadID tid() const { return m_tid; }
|
ThreadID tid() const { return m_tid; }
|
||||||
|
@ -967,14 +968,14 @@ public:
|
||||||
ErrorOr<NonnullRefPtr<Thread>> clone(NonnullRefPtr<Process>);
|
ErrorOr<NonnullRefPtr<Thread>> clone(NonnullRefPtr<Process>);
|
||||||
|
|
||||||
template<IteratorFunction<Thread&> Callback>
|
template<IteratorFunction<Thread&> Callback>
|
||||||
static IterationDecision for_each_in_state(State, Callback);
|
static IterationDecision for_each_in_state_ignoring_jails(State, Callback);
|
||||||
template<IteratorFunction<Thread&> Callback>
|
template<IteratorFunction<Thread&> Callback>
|
||||||
static IterationDecision for_each(Callback);
|
static IterationDecision for_each_ignoring_jails(Callback);
|
||||||
|
|
||||||
template<VoidFunction<Thread&> Callback>
|
template<VoidFunction<Thread&> Callback>
|
||||||
static IterationDecision for_each_in_state(State, Callback);
|
static IterationDecision for_each_in_state_ignoring_jails(State, Callback);
|
||||||
template<VoidFunction<Thread&> Callback>
|
template<VoidFunction<Thread&> Callback>
|
||||||
static IterationDecision for_each(Callback);
|
static IterationDecision for_each_ignoring_jails(Callback);
|
||||||
|
|
||||||
static constexpr u32 default_kernel_stack_size = 65536;
|
static constexpr u32 default_kernel_stack_size = 65536;
|
||||||
static constexpr u32 default_userspace_stack_size = 1 * MiB;
|
static constexpr u32 default_userspace_stack_size = 1 * MiB;
|
||||||
|
@ -1264,7 +1265,7 @@ public:
|
||||||
AK_ENUM_BITWISE_OPERATORS(Thread::FileBlocker::BlockFlags);
|
AK_ENUM_BITWISE_OPERATORS(Thread::FileBlocker::BlockFlags);
|
||||||
|
|
||||||
template<IteratorFunction<Thread&> Callback>
|
template<IteratorFunction<Thread&> Callback>
|
||||||
inline IterationDecision Thread::for_each(Callback callback)
|
inline IterationDecision Thread::for_each_ignoring_jails(Callback callback)
|
||||||
{
|
{
|
||||||
return Thread::all_instances().with([&](auto& list) -> IterationDecision {
|
return Thread::all_instances().with([&](auto& list) -> IterationDecision {
|
||||||
for (auto& thread : list) {
|
for (auto& thread : list) {
|
||||||
|
@ -1277,7 +1278,7 @@ inline IterationDecision Thread::for_each(Callback callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<IteratorFunction<Thread&> Callback>
|
template<IteratorFunction<Thread&> Callback>
|
||||||
inline IterationDecision Thread::for_each_in_state(State state, Callback callback)
|
inline IterationDecision Thread::for_each_in_state_ignoring_jails(State state, Callback callback)
|
||||||
{
|
{
|
||||||
return Thread::all_instances().with([&](auto& list) -> IterationDecision {
|
return Thread::all_instances().with([&](auto& list) -> IterationDecision {
|
||||||
for (auto& thread : list) {
|
for (auto& thread : list) {
|
||||||
|
@ -1292,7 +1293,7 @@ inline IterationDecision Thread::for_each_in_state(State state, Callback callbac
|
||||||
}
|
}
|
||||||
|
|
||||||
template<VoidFunction<Thread&> Callback>
|
template<VoidFunction<Thread&> Callback>
|
||||||
inline IterationDecision Thread::for_each(Callback callback)
|
inline IterationDecision Thread::for_each_ignoring_jails(Callback callback)
|
||||||
{
|
{
|
||||||
return Thread::all_instances().with([&](auto& list) {
|
return Thread::all_instances().with([&](auto& list) {
|
||||||
for (auto& thread : list) {
|
for (auto& thread : list) {
|
||||||
|
@ -1304,9 +1305,9 @@ inline IterationDecision Thread::for_each(Callback callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<VoidFunction<Thread&> Callback>
|
template<VoidFunction<Thread&> Callback>
|
||||||
inline IterationDecision Thread::for_each_in_state(State state, Callback callback)
|
inline IterationDecision Thread::for_each_in_state_ignoring_jails(State state, Callback callback)
|
||||||
{
|
{
|
||||||
return for_each_in_state(state, [&](auto& thread) {
|
return for_each_in_state_ignoring_jails(state, [&](auto& thread) {
|
||||||
callback(thread);
|
callback(thread);
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue