There's no real system here, I just added it to various functions
that I don't believe we ever want to call after initialization
has finished.
With these changes, we're able to unmap 60 KiB of kernel text
after init. :^)
You can now declare functions with UNMAP_AFTER_INIT and they'll get
segregated into a separate kernel section that gets completely
unmapped at the end of initialization.
This can be used for anything we don't need to call once we've booted
into userspace.
There are two nice things about this mechanism:
- It allows us to free up entire pages of memory for other use.
(Note that this patch does not actually make use of the freed
pages yet, but in the future we totally could!)
- It allows us to get rid of obviously dangerous gadgets like
write-to-CR0 and write-to-CR4 which are very useful for an attacker
trying to disable SMAP/SMEP/etc.
I've also made sure to include a helpful panic message in case you
hit a kernel crash because of this protection. :^)
This was needlessly expecting the first backtrace entry function name to
start with '__assertion_failed', which is no longer the case - it's now
something from libsystem.so. Let's just check whether we have an
'assertion' key in the coredump's metadata, just like we do for pledge
violations.
Our TLS implementation relies on the TLS model being "initial-exec".
We previously enforced this by adding the '-ftls-model=initial-exec'
flag in the root CmakeLists file, but that did not affect ports - So
now we put that flag in the gcc spec files.
Closes#5366
If we have a tracer process waiting for us to exec, we need to release
the ptrace lock before stopping ourselves, since otherwise the tracer
will block forever on the lock.
Fixes#5409.
This enabled trivial ASLR bypass for non-dumpable programs by simply
opening /proc/PID/vm before exec'ing.
We now hold the target process's ptrace lock across the refresh/write
operations, and deny access if the process is non-dumpable. The lock
is necessary to prevent a TOCTOU race on Process::is_dumpable() while
the target is exec'ing.
Fixes#5270.
This option causes GCC to generate code to prevent "stack clash" style
attacks where a very large stack allocation is used in to jump over the
stack guard page and into whatever's next to it.
Tweak the PLT trampoline to avoid generating textrels in LibC.
This allows us to share all the LibC mappings, reducing per-process
memory consumption by ~200 KB. :^)
Patch originally by @nico.
To support this, I had to reorganize the "load_elf" function into two
passes. First we map all the dynamic objects, to get their symbols
into the global lookup table. Then we link all the dynamic objects.
So many read-only GOT's! :^)
The dynamic loader will now mark RELRO segments read-only after
performing relocations. This is pretty cool!
Note that this only applies to main executables so far,.
RELRO support for shared libraries will require some reorganizing
of the dynamic loader.
For a data segment that starts at a non-zero offset into a 4KB page and
crosses a 4KB page boundary, we were failing to pad the VM allocation,
which would cause the memcpy() to fail.
Make sure we round the segment bases down, and segment ends up, and the
issue goes away.
sys$mmap() and related syscalls must pad to the nearest page boundary
below the base address *and* above the end address of the specified
range. Since we have to do this in many places, let's make a helper.
FooConstructor::construct() is no longer a dummy but now generates
either code to throw an exception (for interfaces without constructor)
or code to construct the wrapper and its impl object.
Constructor overloads are not currenly handled, but that's not something
we need right now anyway. Instead of regular create() this uses a new
static function create_with_global_object() and passes the WindowObject,
which may be needed - e.g. for XMLHttpRequest, which has an IDL and
JavaScript constructor with no arguments, but needs a DOM::Window in its
create().
Function::length() is computing the right function length based on its
parameters, but we never called it - instead the *function name length*
was being used, which is obviously wrong. How silly! :^)
By default, a Window has a minimum size of 50x50 - ComboBox lists aren't
always this tall. We now set the minimum height of the ComboBox Window
according to the height of three items, or the total height of all the
items in the list, whichever is smaller.
This means there is no longer any unpainted space in the list window
due to the shortfall between the ListBox widget and Window heights,
and the ComboBox list window always remains a comfortable height for
viewing. :^)
This is obviously a requirement for #5374, oops :^)
Also handle errors gracefully, opening a file that isn't PixelPaint JSON
would previously crash.
Closes#5388.