2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/Process.h"
4#include "pedigree/kernel/process/Scheduler.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/Processor.h"
7#include "pedigree/kernel/processor/ProcessorInformation.h"
8#include "pedigree/kernel/syscallError.h"
9#include "pedigree/kernel/utilities/assert.h"
10#include "pedigree/kernel/utilities/utility.h"
12#include "PosixProcess.h"
13#include "PosixSubsystem.h"
15#include "uts-namespace.h"
20size_t namespaceCount = 1;
21uint64_t nextIdentity = 1;
22constexpr size_t MaximumNamespaces = 256;
23size_t localId(
const Thread& thread) {
24 return const_cast<Thread&
>(thread).getId();
32 size_t localId = 0, taskId = 0;
40 bool attached =
false, closed =
false;
45PosixUtsNamespace::PosixUtsNamespace(uint64_t
identity,
const Snapshot& names,
bool charged)
46 : m_Identity(
identity), m_Charged(charged), m_Names(names) {}
47PosixUtsNamespace::~PosixUtsNamespace() {
49 __atomic_sub_fetch(&namespaceCount,
size_t(1), __ATOMIC_RELEASE);
55void PosixUtsNamespace::setName(
bool domain,
const char* bytes,
size_t length) {
58 char* output = domain ? m_Names.domain : m_Names.node;
60 MemoryCopy(output, bytes, length);
61 ByteSet(output + length, 0, 65 - length);
64UtsStatus posix_uts_initial(
UtsRef& result) {
68 if (!initialNamespace) {
70 MemoryCopy(names.node,
"pedigree", 8);
71 MemoryCopy(names.domain,
"(none)", 6);
73 if (!initialNamespace)
74 return UtsStatus::NoMemory;
76 acquired = initialNamespace;
78 result = pedigree_std::move(acquired);
79 return UtsStatus::Success;
82UtsStatus posix_uts_copy(
const UtsRef& source,
UtsRef& result) {
84 return UtsStatus::Missing;
85 const auto names = source->snapshot();
89 if (__atomic_load_n(&namespaceCount, __ATOMIC_ACQUIRE) >= MaximumNamespaces ||
90 nextIdentity == ~uint64_t(0))
91 return UtsStatus::NoSpace;
92 __atomic_add_fetch(&namespaceCount,
size_t(1), __ATOMIC_ACQ_REL);
97 __atomic_sub_fetch(&namespaceCount,
size_t(1), __ATOMIC_RELEASE);
98 return UtsStatus::NoMemory;
100 result = pedigree_std::move(copy);
101 return UtsStatus::Success;
104PreparedUtsThread::PreparedUtsThread() =
default;
105PreparedUtsThread::~PreparedUtsThread() =
default;
106UtsStatus posix_uts_prepare_thread(
const UtsRef& source,
bool copy,
109 return UtsStatus::Missing;
112 const auto status = posix_uts_copy(source, space);
113 if (status != UtsStatus::Success)
118 return UtsStatus::NoMemory;
120 if (!prepared.get()->m_Binding)
121 return UtsStatus::NoMemory;
122 result = pedigree_std::move(prepared);
123 return UtsStatus::Success;
126PosixUtsTarget::PosixUtsTarget() =
default;
129PosixUtsTarget::~PosixUtsTarget() =
default;
130PosixUtsTarget::operator bool()
const {
134PosixNamespaceContext::PosixNamespaceContext()
136PosixNamespaceContext::~PosixNamespaceContext() {
139bool PosixNamespaceContext::valid()
const {
142void PosixNamespaceContext::attach(
Process& process) {
146 assert(!m_View->closed && (!m_View->attached || m_View->processId == process.
getId()));
147 m_View->processId = process.
getId();
148 m_View->attached =
true;
151bool PosixNamespaceContext::acquireThread(
const Thread& thread,
UtsRef& result)
const {
157 if (m_View->closed || !m_View->attached || thread.
getParent()->
getId() != m_View->processId)
159 for (
auto* node = m_View->first; node; node = node->m_Next) {
160 if (node->m_Binding->localId == localId(thread) && node->m_Binding->live) {
161 acquired = node->m_Binding->space;
168 result = pedigree_std::move(acquired);
173 Thread& thread,
bool leader) {
174 assert(m_View && prepared && prepared.get()->m_Binding);
178 assert(m_View->attached && !m_View->closed && thread.
getParent()->
getId() == m_View->processId);
183 for (
auto* node = m_View->first; node; node = node->m_Next)
184 assert(node->m_Binding->localId != localId(thread));
185 prepared.get()->m_Binding->localId = localId(thread);
186 prepared.get()->m_Binding->taskId = thread.
getTaskId();
187 prepared.get()->m_Binding->live =
true;
188 prepared.get()->m_Next = m_View->first;
190 oldLeader = pedigree_std::move(m_View->leader);
191 m_View->leader = prepared.get()->m_Binding;
197void PosixNamespaceContext::promoteExec(
const Thread& thread) {
198 assert(
bool(m_View));
201 for (
auto* node = m_View->first; node; node = node->m_Next) {
202 if (node->m_Binding->localId == localId(thread) && node->m_Binding->live) {
203 node->m_Binding->taskId = thread.
getTaskId();
204 oldLeader = pedigree_std::move(m_View->leader);
205 m_View->leader = node->m_Binding;
212UtsStatus PosixNamespaceContext::replaceThread(
const Thread& thread,
const UtsRef& replacement) {
213 if (!m_View || !replacement)
214 return UtsStatus::Missing;
218 return UtsStatus::Missing;
219 for (
auto* node = m_View->first; node; node = node->m_Next) {
220 if (node->m_Binding->localId == localId(thread) && node->m_Binding->live) {
221 previous = pedigree_std::move(node->m_Binding->space);
222 node->m_Binding->space = replacement;
223 return UtsStatus::Success;
226 return UtsStatus::Missing;
229void PosixNamespaceContext::retireThread(
const Thread& thread) {
230 if (!m_View || __atomic_load_n(&m_View->closed, __ATOMIC_ACQUIRE))
237 auto** link = &m_View->first;
239 if ((*link)->m_Binding->localId == localId(thread)) {
241 *link = retired->m_Next;
242 retired->m_Next =
nullptr;
243 retired->m_Binding->live =
false;
244 previous = pedigree_std::move(retired->m_Binding->space);
245 if (m_View->leader == retired->m_Binding)
246 oldLeader = pedigree_std::move(m_View->leader);
249 link = &(*link)->m_Next;
255void PosixNamespaceContext::close() {
256 if (!m_View || __atomic_load_n(&m_View->closed, __ATOMIC_ACQUIRE))
262 __atomic_store_n(&m_View->closed,
true, __ATOMIC_RELEASE);
263 retired = m_View->first;
264 m_View->first =
nullptr;
265 oldLeader = pedigree_std::move(m_View->leader);
266 for (
auto* node = retired; node; node = node->m_Next)
267 node->m_Binding->live =
false;
270 auto* next = retired->m_Next;
271 retired->m_Binding->space.
reset();
277bool PosixNamespaceContext::leaderTarget(
PosixUtsTarget& result)
const {
283 if (m_View->closed || !m_View->attached)
285 target.m_View = m_View;
291bool PosixNamespaceContext::taskTarget(
size_t taskId,
PosixUtsTarget& result)
const {
297 if (m_View->closed || !m_View->attached)
299 for (
auto* node = m_View->first; node; node = node->m_Next) {
300 if (node->m_Binding->live && node->m_Binding->taskId == taskId) {
301 target.m_View = m_View;
302 target.m_Task = node->m_Binding;
303 target.m_ExpectedTaskId = taskId;
315 return taskTarget(thread.
getTaskId(), result);
318bool PosixNamespaceContext::nextTaskTarget(
size_t afterTaskId,
size_t& taskId,
325 if (m_View->closed || !m_View->attached)
327 for (
auto* node = m_View->first; node; node = node->m_Next) {
328 const size_t id = node->m_Binding->taskId;
329 if (node->m_Binding->live &&
id > afterTaskId &&
330 (!target.m_Task ||
id < target.m_ExpectedTaskId)) {
331 target.m_View = m_View;
332 target.m_Task = node->m_Binding;
333 target.m_ExpectedTaskId = id;
339 taskId = target.m_ExpectedTaskId;
346 return UtsStatus::Missing;
350 return UtsStatus::Missing;
351 if (lease->getType() != Process::Posix || current->
getParent()->getType() != Process::Posix)
352 return UtsStatus::Denied;
358 auto* subsystem =
static_cast<PosixSubsystem*
>(lease->getSubsystem());
361 if (!context || context->m_View != target.m_View)
362 return UtsStatus::Missing;
363 if (current->
getParent() != lease.get()) {
365 const auto destination =
static_cast<PosixProcess*
>(lease.get())->snapshotCredentials();
366 if (!Process::currentFilesystemCredentials(source) || !destination.dumpable ||
367 source.uid != destination.ruid || source.uid != destination.euid ||
368 source.uid != destination.suid || source.gid != destination.rgid ||
369 source.gid != destination.egid || source.gid != destination.sgid)
370 return UtsStatus::Denied;
373 auto binding = target.m_Task ? target.m_Task : target.m_View->leader;
374 if (target.m_View->closed || !binding || !binding->live ||
375 (target.m_Task && binding->taskId != target.m_ExpectedTaskId))
376 return UtsStatus::Missing;
377 acquired = binding->space;
380 return UtsStatus::Missing;
381 result = pedigree_std::move(acquired);
382 return UtsStatus::Success;
385int posix_uts_error(UtsStatus status) {
387 case UtsStatus::Success:
390 case UtsStatus::NoMemory:
391 SYSCALL_ERROR(OutOfMemory);
393 case UtsStatus::NoSpace:
394 SYSCALL_ERROR(NoSpaceLeftOnDevice);
396 case UtsStatus::Missing:
397 SYSCALL_ERROR(DoesNotExist);
399 case UtsStatus::Denied:
400 SYSCALL_ERROR(PermissionDenied);
402 case UtsStatus::Invalid:
403 SYSCALL_ERROR(InvalidArgument);
Memory-mapped file interface.
static MemoryMapManager & instance()
static ProcessorInformation & information()
static Scheduler & instance()
static SharedPointer< T > tryAllocate(Args...)
@ TerminateThread
Exit only this thread during Process exit.
UnwindType getUnwindState()
Process * getParent() const
T * releaseOwnership() noexcept