2020-01-18 11:38:21 +03:00
|
|
|
/*
|
2021-01-11 11:52:18 +03:00
|
|
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
2021-05-06 00:10:56 +03:00
|
|
|
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
2020-01-18 11:38:21 +03:00
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 11:38:21 +03:00
|
|
|
*/
|
|
|
|
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
#include <AK/Singleton.h>
|
2021-01-25 18:07:10 +03:00
|
|
|
#include <Kernel/Debug.h>
|
2019-05-30 19:58:59 +03:00
|
|
|
#include <Kernel/FileSystem/Custody.h>
|
2019-06-07 10:36:51 +03:00
|
|
|
#include <Kernel/FileSystem/FileDescription.h>
|
2020-05-06 18:40:06 +03:00
|
|
|
#include <Kernel/FileSystem/ProcFS.h>
|
2019-04-03 13:25:24 +03:00
|
|
|
#include <Kernel/FileSystem/VirtualFileSystem.h>
|
2019-11-28 23:12:02 +03:00
|
|
|
#include <Kernel/Heap/kmalloc.h>
|
2021-08-10 20:51:28 +03:00
|
|
|
#include <Kernel/Process.h>
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
#include <Kernel/Sections.h>
|
2019-02-03 14:33:11 +03:00
|
|
|
#include <LibC/errno_numbers.h>
|
|
|
|
|
2020-02-16 03:27:42 +03:00
|
|
|
namespace Kernel {
|
|
|
|
|
2021-08-07 22:34:11 +03:00
|
|
|
static Singleton<ProcFSComponentRegistry> s_the;
|
2019-02-03 14:33:11 +03:00
|
|
|
|
2021-07-11 02:40:26 +03:00
|
|
|
ProcFSComponentRegistry& ProcFSComponentRegistry::the()
|
2020-08-09 20:59:26 +03:00
|
|
|
{
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
return *s_the;
|
2020-08-09 20:59:26 +03:00
|
|
|
}
|
|
|
|
|
2021-07-11 02:40:26 +03:00
|
|
|
UNMAP_AFTER_INIT void ProcFSComponentRegistry::initialize()
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
VERIFY(!s_the.is_initialized());
|
|
|
|
s_the.ensure_instance();
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-07-11 02:40:26 +03:00
|
|
|
UNMAP_AFTER_INIT ProcFSComponentRegistry::ProcFSComponentRegistry()
|
2021-07-18 00:15:52 +03:00
|
|
|
: m_root_directory(ProcFSRootDirectory::must_create())
|
2019-08-16 16:35:02 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFS>> ProcFS::try_create()
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFS());
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
ProcFS::ProcFS()
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ProcFS::~ProcFS()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-08-14 15:02:47 +03:00
|
|
|
KResult ProcFS::initialize()
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
auto root_inode = ProcFSComponentRegistry::the().root_directory().to_inode(*this);
|
|
|
|
if (root_inode.is_error())
|
|
|
|
return root_inode.error();
|
2021-09-03 20:11:51 +03:00
|
|
|
m_root_inode = static_ptr_cast<ProcFSDirectoryInode>(root_inode.release_value());
|
2021-08-14 15:39:51 +03:00
|
|
|
|
2021-08-14 15:02:47 +03:00
|
|
|
return KSuccess;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-07-18 02:50:47 +03:00
|
|
|
Inode& ProcFS::root_inode()
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2020-06-24 23:35:56 +03:00
|
|
|
return *m_root_inode;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
ProcFSInode::ProcFSInode(const ProcFS& fs, InodeIndex index)
|
|
|
|
: Inode(const_cast<ProcFS&>(fs), index)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
ProcFSInode::~ProcFSInode()
|
2021-02-19 11:41:35 +03:00
|
|
|
{
|
2020-09-17 22:51:09 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
void ProcFSInode::flush_metadata()
|
2020-09-17 22:51:09 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResult ProcFSInode::add_child(Inode&, const StringView&, mode_t)
|
2020-09-17 22:51:09 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return EROFS;
|
2020-09-17 22:51:09 +03:00
|
|
|
}
|
|
|
|
|
2021-08-28 23:11:16 +03:00
|
|
|
KResultOr<NonnullRefPtr<Inode>> ProcFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return EROFS;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResult ProcFSInode::remove_child(const StringView&)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return EROFS;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResult ProcFSInode::chmod(mode_t)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return EPERM;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-28 23:11:16 +03:00
|
|
|
KResult ProcFSInode::chown(UserID, GroupID)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return EPERM;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResult ProcFSInode::truncate(u64)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return EPERM;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSGlobalInode>> ProcFSGlobalInode::try_create(const ProcFS& fs, const ProcFSExposedComponent& component)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSGlobalInode(fs, component));
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
ProcFSGlobalInode::ProcFSGlobalInode(const ProcFS& fs, const ProcFSExposedComponent& component)
|
|
|
|
: ProcFSInode(fs, component.component_index())
|
|
|
|
, m_associated_component(component)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
void ProcFSGlobalInode::did_seek(FileDescription& description, off_t new_offset)
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
if (new_offset != 0)
|
|
|
|
return;
|
|
|
|
auto result = m_associated_component->refresh_data(description);
|
|
|
|
if (result.is_error()) {
|
|
|
|
// Subsequent calls to read will return EIO!
|
|
|
|
dbgln("ProcFS: Could not refresh contents: {}", result.error());
|
|
|
|
}
|
2020-01-15 14:05:02 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResult ProcFSGlobalInode::attach(FileDescription& description)
|
2021-05-05 22:07:13 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return m_associated_component->refresh_data(description);
|
2021-05-05 22:07:13 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResultOr<size_t> ProcFSGlobalInode::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* fd) const
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return m_associated_component->read_bytes(offset, count, buffer, fd);
|
2020-01-15 14:05:02 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
StringView ProcFSGlobalInode::name() const
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return m_associated_component->name();
|
2020-01-15 14:05:02 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResult ProcFSGlobalInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)>) const
|
2020-09-17 22:51:09 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
VERIFY_NOT_REACHED();
|
2020-09-17 22:51:09 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 14:32:35 +03:00
|
|
|
KResultOr<NonnullRefPtr<Inode>> ProcFSGlobalInode::lookup(StringView)
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
VERIFY_NOT_REACHED();
|
2020-01-15 14:05:02 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
InodeMetadata ProcFSGlobalInode::metadata() const
|
2020-06-24 23:35:56 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
MutexLocker locker(m_inode_lock);
|
|
|
|
InodeMetadata metadata;
|
|
|
|
metadata.inode = { fsid(), m_associated_component->component_index() };
|
|
|
|
metadata.mode = S_IFREG | m_associated_component->required_mode();
|
|
|
|
metadata.uid = m_associated_component->owner_user();
|
|
|
|
metadata.gid = m_associated_component->owner_group();
|
2021-08-29 00:53:29 +03:00
|
|
|
metadata.size = 0;
|
2021-08-10 20:51:28 +03:00
|
|
|
metadata.mtime = m_associated_component->modified_time();
|
|
|
|
return metadata;
|
2020-06-24 23:35:56 +03:00
|
|
|
}
|
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
KResultOr<size_t> ProcFSGlobalInode::write_bytes(off_t offset, size_t count, const UserOrKernelBuffer& buffer, FileDescription* fd)
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
return m_associated_component->write_bytes(offset, count, buffer, fd);
|
2020-01-15 14:05:02 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSDirectoryInode>> ProcFSDirectoryInode::try_create(const ProcFS& procfs, const ProcFSExposedComponent& component)
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSDirectoryInode(procfs, component));
|
2020-01-15 14:05:02 +03:00
|
|
|
}
|
|
|
|
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
ProcFSDirectoryInode::ProcFSDirectoryInode(const ProcFS& fs, const ProcFSExposedComponent& component)
|
2021-08-10 20:51:28 +03:00
|
|
|
: ProcFSGlobalInode(fs, component)
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
ProcFSDirectoryInode::~ProcFSDirectoryInode()
|
2020-01-15 14:05:02 +03:00
|
|
|
{
|
|
|
|
}
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
InodeMetadata ProcFSDirectoryInode::metadata() const
|
2020-06-24 23:35:56 +03:00
|
|
|
{
|
2021-07-18 02:13:34 +03:00
|
|
|
MutexLocker locker(m_inode_lock);
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
InodeMetadata metadata;
|
|
|
|
metadata.inode = { fsid(), m_associated_component->component_index() };
|
2021-06-23 10:29:15 +03:00
|
|
|
metadata.mode = S_IFDIR | m_associated_component->required_mode();
|
|
|
|
metadata.uid = m_associated_component->owner_user();
|
|
|
|
metadata.gid = m_associated_component->owner_group();
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
metadata.size = 0;
|
2021-06-23 15:59:34 +03:00
|
|
|
metadata.mtime = m_associated_component->modified_time();
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
return metadata;
|
2020-06-24 23:35:56 +03:00
|
|
|
}
|
2021-07-11 01:20:38 +03:00
|
|
|
KResult ProcFSDirectoryInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
MutexLocker locker(procfs().m_lock);
|
|
|
|
return m_associated_component->traverse_as_directory(procfs().fsid(), move(callback));
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 14:32:35 +03:00
|
|
|
KResultOr<NonnullRefPtr<Inode>> ProcFSDirectoryInode::lookup(StringView name)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-10 20:51:28 +03:00
|
|
|
MutexLocker locker(procfs().m_lock);
|
2021-08-14 15:39:51 +03:00
|
|
|
auto maybe_component = m_associated_component->lookup(name);
|
|
|
|
if (maybe_component.is_error())
|
|
|
|
return maybe_component.error();
|
|
|
|
|
|
|
|
auto component = maybe_component.release_value();
|
|
|
|
auto maybe_inode = component->to_inode(procfs());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
|
|
|
|
return maybe_inode.release_value();
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSLinkInode>> ProcFSLinkInode::try_create(const ProcFS& procfs, const ProcFSExposedComponent& component)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSLinkInode(procfs, component));
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
|
|
|
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
ProcFSLinkInode::ProcFSLinkInode(const ProcFS& fs, const ProcFSExposedComponent& component)
|
2021-08-10 20:51:28 +03:00
|
|
|
: ProcFSGlobalInode(fs, component)
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
|
|
|
}
|
2021-08-10 20:51:28 +03:00
|
|
|
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
InodeMetadata ProcFSLinkInode::metadata() const
|
2019-02-03 14:33:11 +03:00
|
|
|
{
|
2021-07-18 02:13:34 +03:00
|
|
|
MutexLocker locker(m_inode_lock);
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
InodeMetadata metadata;
|
|
|
|
metadata.inode = { fsid(), m_associated_component->component_index() };
|
|
|
|
metadata.mode = S_IFLNK | m_associated_component->required_mode();
|
2021-06-23 10:29:15 +03:00
|
|
|
metadata.uid = m_associated_component->owner_user();
|
|
|
|
metadata.gid = m_associated_component->owner_group();
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
metadata.size = 0;
|
2021-06-23 15:59:34 +03:00
|
|
|
metadata.mtime = m_associated_component->modified_time();
|
Kernel: Introduce the new ProcFS design
The new ProcFS design consists of two main parts:
1. The representative ProcFS class, which is derived from the FS class.
The ProcFS and its inodes are much more lean - merely 3 classes to
represent the common type of inodes - regular files, symbolic links and
directories. They're backed by a ProcFSExposedComponent object, which
is responsible for the functional operation behind the scenes.
2. The backend of the ProcFS - the ProcFSComponentsRegistrar class
and all derived classes from the ProcFSExposedComponent class. These
together form the entire backend and handle all the functions you can
expect from the ProcFS.
The ProcFSExposedComponent derived classes split to 3 types in the
manner of lifetime in the kernel:
1. Persistent objects - this category includes all basic objects, like
the root folder, /proc/bus folder, main blob files in the root folders,
etc. These objects are persistent and cannot die ever.
2. Semi-persistent objects - this category includes all PID folders,
and subdirectories to the PID folders. It also includes exposed objects
like the unveil JSON'ed blob. These object are persistent as long as the
the responsible process they represent is still alive.
3. Dynamic objects - this category includes files in the subdirectories
of a PID folder, like /proc/PID/fd/* or /proc/PID/stacks/*. Essentially,
these objects are always created dynamically and when no longer in need
after being used, they're deallocated.
Nevertheless, the new allocated backend objects and inodes try to use
the same InodeIndex if possible - this might change only when a thread
dies and a new thread is born with a new thread stack, or when a file
descriptor is closed and a new one within the same file descriptor
number is opened. This is needed to actually be able to do something
useful with these objects.
The new design assures that many ProcFS instances can be used at once,
with one backend for usage for all instances.
2021-06-12 04:23:58 +03:00
|
|
|
return metadata;
|
2019-02-03 14:33:11 +03:00
|
|
|
}
|
2019-02-27 14:32:53 +03:00
|
|
|
|
2021-08-10 20:51:28 +03:00
|
|
|
ProcFSProcessAssociatedInode::ProcFSProcessAssociatedInode(const ProcFS& fs, ProcessID associated_pid, InodeIndex determined_index)
|
|
|
|
: ProcFSInode(fs, determined_index)
|
|
|
|
, m_pid(associated_pid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
KResultOr<size_t> ProcFSProcessAssociatedInode::write_bytes(off_t, size_t, const UserOrKernelBuffer&, FileDescription*)
|
|
|
|
{
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSProcessDirectoryInode>> ProcFSProcessDirectoryInode::try_create(const ProcFS& procfs, ProcessID pid)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessDirectoryInode(procfs, pid));
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ProcFSProcessDirectoryInode::ProcFSProcessDirectoryInode(const ProcFS& procfs, ProcessID pid)
|
|
|
|
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_pid_directory(pid))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
KResult ProcFSProcessDirectoryInode::attach(FileDescription&)
|
|
|
|
{
|
|
|
|
return KSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
InodeMetadata ProcFSProcessDirectoryInode::metadata() const
|
|
|
|
{
|
|
|
|
MutexLocker locker(m_inode_lock);
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
|
|
|
return {};
|
2021-08-14 15:43:34 +03:00
|
|
|
|
|
|
|
auto traits = process->procfs_traits();
|
2021-08-10 20:51:28 +03:00
|
|
|
InodeMetadata metadata;
|
2021-08-14 15:43:34 +03:00
|
|
|
metadata.inode = { fsid(), traits->component_index() };
|
|
|
|
metadata.mode = S_IFDIR | traits->required_mode();
|
|
|
|
metadata.uid = traits->owner_user();
|
|
|
|
metadata.gid = traits->owner_group();
|
2021-08-10 20:51:28 +03:00
|
|
|
metadata.size = 0;
|
2021-08-14 15:43:34 +03:00
|
|
|
metadata.mtime = traits->modified_time();
|
2021-08-10 20:51:28 +03:00
|
|
|
return metadata;
|
|
|
|
}
|
|
|
|
|
|
|
|
KResultOr<size_t> ProcFSProcessDirectoryInode::read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const
|
|
|
|
{
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
|
|
|
KResult ProcFSProcessDirectoryInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
|
|
|
|
{
|
|
|
|
MutexLocker locker(procfs().m_lock);
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
|
|
|
return EINVAL;
|
2021-08-14 15:43:34 +03:00
|
|
|
return process->procfs_traits()->traverse_as_directory(procfs().fsid(), move(callback));
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 14:32:35 +03:00
|
|
|
KResultOr<NonnullRefPtr<Inode>> ProcFSProcessDirectoryInode::lookup(StringView name)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
|
|
|
MutexLocker locker(procfs().m_lock);
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
2021-08-14 14:32:35 +03:00
|
|
|
return ESRCH;
|
2021-08-14 15:39:51 +03:00
|
|
|
if (name == "fd") {
|
|
|
|
auto maybe_inode = ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::FileDescriptions, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "stacks") {
|
|
|
|
auto maybe_inode = ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "unveil") {
|
|
|
|
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Unveil, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "pledge") {
|
|
|
|
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Pledge, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "fds") {
|
|
|
|
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::FileDescriptions, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "exe") {
|
|
|
|
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::BinaryLink, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "cwd") {
|
|
|
|
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "perf_events") {
|
|
|
|
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
if (name == "vm") {
|
|
|
|
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats, associated_pid());
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
|
2021-08-14 14:32:35 +03:00
|
|
|
return ENOENT;
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSProcessSubDirectoryInode>> ProcFSProcessSubDirectoryInode::try_create(const ProcFS& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessSubDirectoryInode(procfs, sub_directory_type, pid));
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ProcFSProcessSubDirectoryInode::ProcFSProcessSubDirectoryInode(const ProcFS& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid)
|
|
|
|
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(pid, sub_directory_type))
|
|
|
|
, m_sub_directory_type(sub_directory_type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
KResultOr<size_t> ProcFSProcessSubDirectoryInode::read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const
|
|
|
|
{
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
|
|
|
KResult ProcFSProcessSubDirectoryInode::attach(FileDescription&)
|
|
|
|
{
|
|
|
|
return KSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProcFSProcessSubDirectoryInode::did_seek(FileDescription&, off_t)
|
|
|
|
{
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
|
|
|
InodeMetadata ProcFSProcessSubDirectoryInode::metadata() const
|
|
|
|
{
|
|
|
|
MutexLocker locker(m_inode_lock);
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
|
|
|
return {};
|
2021-08-14 15:43:34 +03:00
|
|
|
|
|
|
|
auto traits = process->procfs_traits();
|
2021-08-10 20:51:28 +03:00
|
|
|
InodeMetadata metadata;
|
2021-08-14 15:43:34 +03:00
|
|
|
metadata.inode = { fsid(), traits->component_index() };
|
|
|
|
metadata.mode = S_IFDIR | traits->required_mode();
|
|
|
|
metadata.uid = traits->owner_user();
|
|
|
|
metadata.gid = traits->owner_group();
|
2021-08-10 20:51:28 +03:00
|
|
|
metadata.size = 0;
|
2021-08-14 15:43:34 +03:00
|
|
|
metadata.mtime = traits->modified_time();
|
2021-08-10 20:51:28 +03:00
|
|
|
return metadata;
|
|
|
|
}
|
|
|
|
|
|
|
|
KResult ProcFSProcessSubDirectoryInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
|
|
|
|
{
|
|
|
|
MutexLocker locker(procfs().m_lock);
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
|
|
|
return EINVAL;
|
|
|
|
switch (m_sub_directory_type) {
|
|
|
|
case SegmentedProcFSIndex::ProcessSubDirectory::FileDescriptions:
|
|
|
|
return process->traverse_file_descriptions_directory(procfs().fsid(), move(callback));
|
|
|
|
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
|
|
|
return process->traverse_stacks_directory(procfs().fsid(), move(callback));
|
|
|
|
default:
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
2021-08-14 14:32:35 +03:00
|
|
|
KResultOr<NonnullRefPtr<Inode>> ProcFSProcessSubDirectoryInode::lookup(StringView name)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
|
|
|
MutexLocker locker(procfs().m_lock);
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
2021-08-14 14:32:35 +03:00
|
|
|
return ESRCH;
|
|
|
|
RefPtr<Inode> inode;
|
2021-08-10 20:51:28 +03:00
|
|
|
switch (m_sub_directory_type) {
|
2021-08-14 15:39:51 +03:00
|
|
|
case SegmentedProcFSIndex::ProcessSubDirectory::FileDescriptions: {
|
|
|
|
auto maybe_inode = process->lookup_file_descriptions_directory(procfs(), name);
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
|
|
|
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks: {
|
|
|
|
auto maybe_inode = process->lookup_stacks_directory(procfs(), name);
|
|
|
|
if (maybe_inode.is_error())
|
|
|
|
return maybe_inode.error();
|
|
|
|
return maybe_inode.release_value();
|
|
|
|
}
|
2021-08-10 20:51:28 +03:00
|
|
|
default:
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
2021-08-14 14:32:35 +03:00
|
|
|
if (!inode)
|
|
|
|
return ENOENT;
|
|
|
|
return inode.release_nonnull();
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
|
|
|
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_file_description_link(const ProcFS& procfs, unsigned file_description_index, ProcessID pid)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, file_description_index, pid));
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_thread_stack(const ProcFS& procfs, ThreadID stack_thread_index, ProcessID pid)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, stack_thread_index, pid));
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
2021-08-14 15:39:51 +03:00
|
|
|
KResultOr<NonnullRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_pid_property(const ProcFS& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
2021-08-14 15:39:51 +03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, main_property_type, pid));
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(const ProcFS& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid)
|
|
|
|
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(pid, main_property_type))
|
|
|
|
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Reserved)
|
|
|
|
{
|
|
|
|
m_possible_data.property_type = main_property_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(const ProcFS& procfs, unsigned file_description_index, ProcessID pid)
|
|
|
|
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_file_description(pid, file_description_index))
|
|
|
|
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::FileDescriptions)
|
|
|
|
{
|
|
|
|
m_possible_data.property_index = file_description_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(const ProcFS& procfs, ThreadID thread_stack_index, ProcessID pid)
|
|
|
|
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_thread_stack(pid, thread_stack_index))
|
|
|
|
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
|
|
|
{
|
|
|
|
m_possible_data.property_index = thread_stack_index.value();
|
|
|
|
}
|
|
|
|
|
|
|
|
KResult ProcFSProcessPropertyInode::attach(FileDescription& description)
|
|
|
|
{
|
|
|
|
return refresh_data(description);
|
|
|
|
}
|
|
|
|
void ProcFSProcessPropertyInode::did_seek(FileDescription& description, off_t offset)
|
|
|
|
{
|
|
|
|
if (offset != 0)
|
|
|
|
return;
|
|
|
|
(void)refresh_data(description);
|
|
|
|
}
|
|
|
|
|
|
|
|
static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessSubDirectory parent_sub_directory_type, SegmentedProcFSIndex::MainProcessProperty main_property)
|
|
|
|
{
|
|
|
|
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::FileDescriptions)
|
|
|
|
return S_IFLNK | 0400;
|
|
|
|
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
|
|
|
return S_IFREG | 0400;
|
|
|
|
VERIFY(parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
|
|
|
if (main_property == SegmentedProcFSIndex::MainProcessProperty::BinaryLink)
|
|
|
|
return S_IFLNK | 0777;
|
|
|
|
if (main_property == SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink)
|
|
|
|
return S_IFLNK | 0777;
|
|
|
|
return S_IFREG | 0400;
|
|
|
|
}
|
|
|
|
|
|
|
|
InodeMetadata ProcFSProcessPropertyInode::metadata() const
|
|
|
|
{
|
|
|
|
MutexLocker locker(m_inode_lock);
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
|
|
|
return {};
|
2021-08-14 15:43:34 +03:00
|
|
|
|
|
|
|
auto traits = process->procfs_traits();
|
2021-08-10 20:51:28 +03:00
|
|
|
InodeMetadata metadata;
|
2021-08-14 15:43:34 +03:00
|
|
|
metadata.inode = { fsid(), traits->component_index() };
|
2021-08-10 20:51:28 +03:00
|
|
|
metadata.mode = determine_procfs_process_inode_mode(m_parent_sub_directory_type, m_possible_data.property_type);
|
2021-08-14 15:43:34 +03:00
|
|
|
metadata.uid = traits->owner_user();
|
|
|
|
metadata.gid = traits->owner_group();
|
2021-08-10 20:51:28 +03:00
|
|
|
metadata.size = 0;
|
2021-08-14 15:43:34 +03:00
|
|
|
metadata.mtime = traits->modified_time();
|
2021-08-10 20:51:28 +03:00
|
|
|
return metadata;
|
|
|
|
}
|
|
|
|
KResult ProcFSProcessPropertyInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)>) const
|
|
|
|
{
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
KResultOr<size_t> ProcFSProcessPropertyInode::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* description) const
|
|
|
|
{
|
|
|
|
dbgln_if(PROCFS_DEBUG, "ProcFS ProcessInformation: read_bytes offset: {} count: {}", offset, count);
|
|
|
|
|
|
|
|
VERIFY(offset >= 0);
|
|
|
|
VERIFY(buffer.user_or_kernel_ptr());
|
|
|
|
|
|
|
|
if (!description) {
|
|
|
|
KBufferBuilder builder;
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
|
|
|
return KResult(ESRCH);
|
|
|
|
if (auto result = try_to_acquire_data(*process, builder); result.is_error())
|
2021-08-13 19:20:32 +03:00
|
|
|
return result;
|
2021-08-10 20:51:28 +03:00
|
|
|
auto data_buffer = builder.build();
|
|
|
|
if (!data_buffer)
|
|
|
|
return KResult(EFAULT);
|
|
|
|
ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
|
|
|
|
if (!buffer.write(data_buffer->data() + offset, nread))
|
|
|
|
return KResult(EFAULT);
|
|
|
|
return nread;
|
|
|
|
}
|
|
|
|
if (!description->data()) {
|
|
|
|
dbgln("ProcFS Process Information: Do not have cached data!");
|
|
|
|
return KResult(EIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
MutexLocker locker(m_refresh_lock);
|
|
|
|
|
|
|
|
auto& typed_cached_data = static_cast<ProcFSInodeData&>(*description->data());
|
|
|
|
auto& data_buffer = typed_cached_data.buffer;
|
|
|
|
|
|
|
|
if (!data_buffer || (size_t)offset >= data_buffer->size())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
|
|
|
|
if (!buffer.write(data_buffer->data() + offset, nread))
|
|
|
|
return KResult(EFAULT);
|
|
|
|
|
|
|
|
return nread;
|
|
|
|
}
|
2021-08-14 14:32:35 +03:00
|
|
|
KResultOr<NonnullRefPtr<Inode>> ProcFSProcessPropertyInode::lookup(StringView)
|
2021-08-10 20:51:28 +03:00
|
|
|
{
|
2021-08-14 14:32:35 +03:00
|
|
|
return EINVAL;
|
2021-08-10 20:51:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static KResult build_from_cached_data(KBufferBuilder& builder, ProcFSInodeData& cached_data)
|
|
|
|
{
|
|
|
|
cached_data.buffer = builder.build();
|
|
|
|
if (!cached_data.buffer)
|
|
|
|
return ENOMEM;
|
|
|
|
return KSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
KResult ProcFSProcessPropertyInode::try_to_acquire_data(Process& process, KBufferBuilder& builder) const
|
|
|
|
{
|
|
|
|
// FIXME: Verify process is already ref-counted
|
|
|
|
if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::FileDescriptions) {
|
|
|
|
if (auto result = process.procfs_get_file_description_link(m_possible_data.property_index, builder); result.is_error())
|
|
|
|
return result.error();
|
|
|
|
return KSuccess;
|
|
|
|
}
|
|
|
|
if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks) {
|
|
|
|
if (auto result = process.procfs_get_thread_stack(m_possible_data.property_index, builder); result.is_error())
|
|
|
|
return result.error();
|
|
|
|
return KSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
VERIFY(m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
|
|
|
switch (m_possible_data.property_type) {
|
|
|
|
case SegmentedProcFSIndex::MainProcessProperty::Unveil:
|
2021-08-14 08:09:39 +03:00
|
|
|
return process.procfs_get_unveil_stats(builder);
|
2021-08-10 20:51:28 +03:00
|
|
|
case SegmentedProcFSIndex::MainProcessProperty::Pledge:
|
|
|
|
return process.procfs_get_pledge_stats(builder);
|
|
|
|
case SegmentedProcFSIndex::MainProcessProperty::FileDescriptions:
|
|
|
|
return process.procfs_get_fds_stats(builder);
|
|
|
|
case SegmentedProcFSIndex::MainProcessProperty::BinaryLink:
|
|
|
|
return process.procfs_get_binary_link(builder);
|
|
|
|
case SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink:
|
|
|
|
return process.procfs_get_current_work_directory_link(builder);
|
|
|
|
case SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents:
|
|
|
|
return process.procfs_get_perf_events(builder);
|
|
|
|
case SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats:
|
|
|
|
return process.procfs_get_virtual_memory_stats(builder);
|
|
|
|
default:
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KResult ProcFSProcessPropertyInode::refresh_data(FileDescription& description)
|
|
|
|
{
|
|
|
|
// For process-specific inodes, hold the process's ptrace lock across refresh
|
|
|
|
// and refuse to load data if the process is not dumpable.
|
|
|
|
// Without this, files opened before a process went non-dumpable could still be used for dumping.
|
|
|
|
auto process = Process::from_pid(associated_pid());
|
|
|
|
if (!process)
|
|
|
|
return KResult(ESRCH);
|
|
|
|
process->ptrace_lock().lock();
|
|
|
|
if (!process->is_dumpable()) {
|
|
|
|
process->ptrace_lock().unlock();
|
|
|
|
return EPERM;
|
|
|
|
}
|
|
|
|
ScopeGuard guard = [&] {
|
|
|
|
process->ptrace_lock().unlock();
|
|
|
|
};
|
|
|
|
MutexLocker locker(m_refresh_lock);
|
|
|
|
auto& cached_data = description.data();
|
|
|
|
if (!cached_data) {
|
|
|
|
cached_data = adopt_own_if_nonnull(new (nothrow) ProcFSInodeData);
|
|
|
|
if (!cached_data)
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
KBufferBuilder builder;
|
|
|
|
if (auto result = try_to_acquire_data(*process, builder); result.is_error())
|
|
|
|
return result;
|
|
|
|
return build_from_cached_data(builder, static_cast<ProcFSInodeData&>(*cached_data));
|
|
|
|
}
|
2020-02-16 03:27:42 +03:00
|
|
|
}
|