Serenity Operating System
1/*
2 * Copyright (c) 2022-2023, Liav A. <liavalb@hotmail.co.il>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/IntrusiveList.h>
8#include <AK/Singleton.h>
9#include <Kernel/Jail.h>
10#include <Kernel/Process.h>
11
12namespace Kernel {
13
14static Atomic<u64> s_jail_id;
15static Singleton<SpinlockProtected<Jail::List, LockRank::None>> s_all_instances {};
16
17static JailIndex generate_jail_id()
18{
19 return s_jail_id.fetch_add(1);
20}
21
22NonnullRefPtr<ProcessList> Jail::process_list()
23{
24 return m_process_list;
25}
26
27ErrorOr<NonnullLockRefPtr<Jail>> Jail::create(NonnullOwnPtr<KString> name)
28{
29 return s_all_instances->with([&](auto& list) -> ErrorOr<NonnullLockRefPtr<Jail>> {
30 auto process_list = TRY(ProcessList::create());
31 auto jail = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) Jail(move(name), generate_jail_id(), move(process_list))));
32 list.append(jail);
33 return jail;
34 });
35}
36
37ErrorOr<void> Jail::for_each_when_process_is_not_jailed(Function<ErrorOr<void>(Jail const&)> callback)
38{
39 return Process::current().jail().with([&](auto const& my_jail) -> ErrorOr<void> {
40 // Note: If we are in a jail, don't reveal anything about the outside world,
41 // not even the fact that we are in which jail...
42 if (my_jail)
43 return {};
44 return s_all_instances->with([&](auto& list) -> ErrorOr<void> {
45 for (auto& jail : list) {
46 TRY(callback(jail));
47 }
48 return {};
49 });
50 });
51}
52
53LockRefPtr<Jail> Jail::find_by_index(JailIndex index)
54{
55 return s_all_instances->with([&](auto& list) -> LockRefPtr<Jail> {
56 for (auto& jail : list) {
57 if (jail.index() == index)
58 return jail;
59 }
60 return {};
61 });
62}
63
64Jail::Jail(NonnullOwnPtr<KString> name, JailIndex index, NonnullRefPtr<ProcessList> process_list)
65 : m_name(move(name))
66 , m_index(index)
67 , m_process_list(move(process_list))
68{
69}
70
71void Jail::detach(Badge<Process>)
72{
73 VERIFY(ref_count() > 0);
74 m_attach_count.with([&](auto& my_attach_count) {
75 VERIFY(my_attach_count > 0);
76 my_attach_count--;
77 if (my_attach_count == 0) {
78 m_list_node.remove();
79 }
80 });
81}
82
83}