When creating uninitialized storage for variables, we need to make sure
that the alignment is correct. Fixes a KUBSAN failure when running
kernels compiled with Clang.
In `Syscalls/socket.cpp`, we can simply use local variables, as
`sockaddr_un` is a POD type.
Along with moving the `alignas` specifier to the correct member,
`AK::Optional`'s internal buffer has been made non-zeroed by default.
GCC emitted bogus uninitialized memory access warnings, so we now use
`__builtin_launder` to tell the compiler that we know what we are doing.
This might disable some optimizations, but judging by how GCC failed to
notice that the memory's initialization is dependent on `m_has_value`,
I'm not sure that's a bad thing.
The `#pragma GCC diagnostic` part is needed because the class has
virtual methods with the same name but different arguments, and Clang
tries to warn us that we are not actually overriding anything with
these.
Weirdly enough, GCC does not seem to care.
Now we use WeakPtrs to break Ref-counting cycle. Also, we call the
prepare_for_deletion method to ensure deleted objects are ready for
deletion. This is necessary to ensure we don't keep dead processes,
which would become zombies.
In addition to that, add some debug prints to aid debug in the future.
This changes the m_parts, m_dirname, m_basename, m_title and m_extension
member variables to StringViews onto the m_string String. It also
removes the m_is_absolute member in favour of computing if a path is
absolute in the is_absolute() getter. Due to this, the canonicalize()
method has been completely rewritten.
The parts() getter still returns a Vector<String>, although it is no
longer a const reference as m_parts is no longer a Vector<String>.
Rather, it is constructed from the StringViews in m_parts upon request.
The parts_view() getter has been added, which returns Vector<StringView>
const&. Most previous users of parts() have been changed to use
parts_view(), except where Strings are required.
Due to this change, it's is now no longer allow to create temporary
LexicalPath objects to call the dirname, basename, title, or extension
getters on them because the returned StringViews will point to possible
freed memory.
The LexicalPath instance methods dirname(), basename(), title() and
extension() will be changed to return StringView const& in a further
commit. Due to this, users creating temporary LexicalPath objects just
to call one of those getters will recieve a StringView const& pointing
to a possible freed buffer.
To avoid this, static methods for those APIs have been added, which will
return a String by value to avoid those problems. All cases where
temporary LexicalPath objects have been used as described above haven
been changed to use the static APIs.
There is a check in map_bus_region to make sure we don't pointlessly
remap the bus region if the previous mapping was for the same bus.
This is tracked with `m_mapped_bus`.
However, nothing was actually updating `m_mapped_bus`, and it is
initialised to 0. This means that if we start with a device on bus 0,
the read in data will be valid. If we map say bus 1 then bus 0 again,
the map for bus 0 will now be ignored and invalid data will be read in.
Fixed by updating `m_mapped_bus` with the currently mapped bus.
This hack allows self-test mode run-tests-and-shutdown.sh to give
TestProcFs a stat(2)-able /proc/self/fd/0. For some reason, when
stdin is a SerialDevice, /proc/self/fd/0 will be a symlink to the device
as expected, but, calling realpath or stat on /proc/self/fd/0 will error
out. realpath will give the string from Device::absolute_path() which
would be something like "device:4,64 (SerialDevice)". When VFS is trying
to resolve_path so that we can stat the file, it would bail out on this
fake-y path.
Change the fake path (that doesn't show up when you ls a device, nor
when checking the devices tab in SystemMonitor) from the major/minor
device number and class_name() to /dev/device_name(). There's probably
a very hairy yak standing behind this issue that was only discovered due
to the ProcFS rework.
I regressed this in 648480f715.
We have to make sure JsonObjectSerializer::finish() is called before
writing out the blob. This is done automatically when the serializer
is destroyed, so just wrap them in scopes.
It didn't make any sense to hardcode the modified time of all created
inodes with "mepoch", so we should query the procfs "backend" to get
the modified time value.
Since ProcFS is dynamically changed all the time, the modified time
equals to the querying time.
This could be changed if desired, by making the modified_time()
method virtual and overriding it in different procfs-backed objects :)
Instead of using one file for the entire "backend" of the ProcFS data
and metadata, we could split that file into two files that represent
2 logical chunks of the ProcFS exposed objects:
1. Global and inter-process information. This includes all fixed data in
the root folder of the ProcFS, networking information and the bus
folder.
2. Per-process information. This includes all dynamic data about a
process that resides in the /proc/PID/ folder.
This change makes it more easier to read the code and to change it,
hence we do it although there's no technical benefit from it now :)
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.
The intention is to add dynamic mechanism for notifying the userspace
about hotplug events. Currently, the DMI (SMBIOS) blobs and ACPI tables
are exposed in the new filesystem.
This does the exact thing as `adopt_ref`, which is a recent addition to
AK.
Note that pointers returned by a bare new (without `nothrow`) are
guaranteed not to return null, so they can safely be converted into
references.
This optimization has already been done in LibC's `assert.h`, which
Userland `VERIFY()` calls resolve to. We now use it in the kernel, but
with the nicer C++ *unlikely* attribute instead of `__builtin_expect`.
This tells the compiler to arrange the generated machine code so that
the error-free branches execute faster (e.g. fewer jumps, better cache
locality).