Commit graph

1196 commits

Author SHA1 Message Date
Andreas Kling
90c0f9664e Kernel: Don't keep protected Process data in a separate allocation
The previous architecture had a huge flaw: the pointer to the protected
data was itself unprotected, allowing you to overwrite it at any time.

This patch reorganizes the protected data so it's part of the Process
class itself. (Actually, it's a new ProcessBase helper class.)

We use the first 4 KB of Process objects themselves as the new storage
location for protected data. Then we make Process objects page-aligned
using MAKE_ALIGNED_ALLOCATED.

This allows us to easily turn on/off write-protection for everything in
the ProcessBase portion of Process. :^)

Thanks to @bugaevc for pointing out the flaw! This is still not perfect
but it's an improvement.
2021-03-11 14:21:49 +01:00
Andreas Kling
de6c5128fd Kernel: Move process pledge promises into protected data 2021-03-10 22:50:00 +01:00
Andreas Kling
3d27269f13 Kernel: Move process parent PID into protected data :^) 2021-03-10 22:30:02 +01:00
Andreas Kling
d677a73b0e Kernel: Move process extra_gids into protected data :^) 2021-03-10 22:30:02 +01:00
Andreas Kling
cbcf891040 Kernel: Move select Process members into protected memory
Process member variable like m_euid are very valuable targets for
kernel exploits and until now they have been writable at all times.

This patch moves m_euid along with a whole bunch of other members
into a new Process::ProtectedData struct. This struct is remapped
as read-only memory whenever we don't need to write to it.

This means that a kernel write primitive is no longer enough to
overwrite a process's effective UID, you must first unprotect the
protected data where the UID is stored. :^)
2021-03-10 22:30:02 +01:00
Andreas Kling
84725ef3a5 Kernel+UserspaceEmulator: Add sys$emuctl() system call
This returns ENOSYS if you are running in the real kernel, and some
other result if you are running in UserspaceEmulator.

There are other ways we could check if we're inside an emulator, but
it seemed easier to just ask. :^)
2021-03-09 08:58:26 +01:00
Brian Gianforcaro
5f6ab77352 Kernel: Add bitwise operators for Thread::FileBlocker::BlockFlags enum
Switch to using type-safe bitwise operators for the BlockFlags class,
this cleans up a lot of boilerplate casts which are necessary when the
enum is declared as `enum class`.
2021-03-08 18:47:40 +01:00
Ben Wiederhake
501952852c Kernel: Fix pointer over/underflow in create_thread
The expression
    (u8*)params.m_stack_location + stack_size
… causes UBSan to spit out the warning
    KUBSAN: addition of unsigned offset to 0x00000002 overflowed to 0xb0000003
… even though there is no actual overflow happening here.
This can be reproduced by running:
    $ syscall create_thread 0 [ 0 0 0 0 0xb0000001 2 ]
Technically, this is a true-positive: The C++-reference is incredibly strict
about pointer-arithmetic:
    > A pointer to non-array object is treated as a pointer to the first element
    > of an array with size 1. […] [A]ttempts to generate a pointer that isn't
    > pointing at an element of the same array or one past the end invoke
    > undefined behavior.
    https://en.cppreference.com/w/cpp/language/operator_arithmetic
Frankly, this feels silly. So let's just use FlatPtr instead.

Found by fuzz-syscalls. Undocumented bug.

Note that FlatPtr is an unsigned type, so
    user_esp.value() - 4
is defined even if we end up with a user_esp of 0 (this can happen for example
when params.m_stack_size = 0 and params.m_stack_location = 0). The result would
be a Kernelspace-pointer, which would then be immediately flagged by
'MM.validate_user_stack' as invalid, as intended.
2021-03-07 17:31:25 +01:00
Andreas Kling
a819eb5016 Kernel: Skip TLB flushes while cloning regions in sys$fork()
Since we know for sure that the virtual memory regions in the new
process being created are not being used on any CPU, there's no need
to do TLB flushes for every mapped page.
2021-03-03 22:57:45 +01:00
Andreas Kling
d96a44a738 Kernel: Avoid transient kmalloc heap allocations in sys$select()
Dynamic Vector allocations in sys$select() were showing up in the
full-system profile and since there will never be more than FD_SETSIZE
file descriptors to worry about, we can confidently add enough inline
capacity to this Vector that it never has to kmalloc.

To compensate for the increased stack usage, reduce the size of the
FDInfo struct while we're here. :^)
2021-03-03 20:37:23 +01:00
Andreas Kling
5e7abea31e Kernel+Profiler: Capture metadata about all profiled processes
The perfcore file format was previously limited to a single process
since the pid/executable/regions data was top-level in the JSON.

This patch moves the process-specific data into a top-level array
named "processes" and we now add entries for each process that has
been sampled during the profile run.

This makes it possible to see samples from multiple threads when
viewing a perfcore file with Profiler. This is extremely cool! :^)
2021-03-02 22:38:06 +01:00
Andreas Kling
ea500dd3e3 Kernel: Start work on full system profiling :^)
The superuser can now call sys$profiling_enable() with PID -1 to enable
profiling of all running threads in the system. The perf events are
collected in a global PerformanceEventBuffer (currently 32 MiB in size.)

The events can be accessed via /proc/profile
2021-03-02 22:38:06 +01:00
Andreas Kling
b425c2602c Kernel: Better handling of allocation failure in profiling
If we can't allocate a PerformanceEventBuffer to store the profiling
events, we now fail sys$profiling_enable() and sys$perf_event()
with ENOMEM instead of carrying on with a broken buffer.
2021-03-02 22:38:06 +01:00
Ben Wiederhake
5c15ca7b84 Kernel: Make sockets use AK::Time 2021-03-02 08:36:08 +01:00
Ben Wiederhake
336303bda4 Kernel: Make kgettimeofday use AK::Time 2021-03-02 08:36:08 +01:00
Ben Wiederhake
c040e64b7d Kernel: Make TimeManagement use AK::Time internally
I don't dare touch the multi-threading logic and locking mechanism, so it stays
timespec for now. However, this could and should be changed to AK::Time, and I
bet it will simplify the "increment_time_since_boot()" code.
2021-03-02 08:36:08 +01:00
Ben Wiederhake
2b6546c40a Kernel: Make Thread use AK::Time internally
This commit is very invasive, because Thread likes to take a pointer and write
to it. This means that translating between timespec/timeval/Time would have been
more difficult than just changing everything that hands a raw pointer to Thread,
in bulk.
2021-03-02 08:36:08 +01:00
Ben Wiederhake
8598240193 Kernel: Sanitize all user-supplied timeval's/timespec's
This also removes a bunch of unnecessary EINVAL. Most of them weren't even
recommended by POSIX.
2021-03-02 08:36:08 +01:00
Andreas Kling
4d006de2b9 Kernel: Fix build with IO_DEBUG 2021-03-01 16:07:50 +01:00
Andreas Kling
272c2e6ec5 Kernel: Use Userspace<T> in sys${munmap,mprotect,madvise,msyscall}() 2021-03-01 15:53:33 +01:00
Andreas Kling
bebceaa32c Kernel: Use Userspace<T> in sys$select() 2021-03-01 15:07:01 +01:00
Andreas Kling
a1a82c1d95 Kernel: Use Userspace<T> in sys$get_dir_entries() 2021-03-01 15:04:31 +01:00
Andreas Kling
b5f32be577 Kernel: Use Userspace<T> in sys$get_stack_bounds() 2021-03-01 14:50:36 +01:00
Andreas Kling
122c7b6cbb Kernel: Use Userspace<T> in sys$write() 2021-03-01 14:35:06 +01:00
Andreas Kling
6a6eb8844a Kernel: Use Userspace<T> in sys$sigaction()
fuzz-syscalls found a bunch of unaligned accesses into struct sigaction
via this syscall. This patch fixes that issue by porting the syscall
to Userspace<T> which we should have done anyway. :^)

Fixes #5500.
2021-03-01 14:06:20 +01:00
Andreas Kling
ac71775de5 Kernel: Make all syscall functions return KResultOr<T>
This makes it a lot easier to return errors since we no longer have to
worry about negating EFOO errors and can just return them flat.
2021-03-01 13:54:32 +01:00
Andreas Kling
4aa58aaab5 Kernel: Don't disable interrupts while exiting a thread or process
This was another vestige from a long time ago, when exiting a thread
would mutate global data structures that were only protected by the
interrupt flag.
2021-02-25 19:36:36 +01:00
Andreas Kling
8eeb8db2ed Kernel: Don't disable interrupts while dealing with a process crash
This was necessary in the past when crash handling would modify
various global things, but all that stuff is long gone so we can
simplify crashes by leaving the interrupt flag alone.
2021-02-25 19:36:36 +01:00
Andreas Kling
8129f3da52 Kernel: Move SMAP disabler RAII helper to its own file
Added this in a new directory called Kernel/Arch/x86/ where stuff
that applies to both i386 and x86_64 can live.
2021-02-25 17:25:34 +01:00
Andreas Kling
8f70528f30 Kernel: Take some baby steps towards x86_64
Make more of the kernel compile in 64-bit mode, and make some things
pointer-size-agnostic (by using FlatPtr.)

There's a lot of work to do here before the kernel will even compile.
2021-02-25 16:27:12 +01:00
Andreas Kling
c11511a0ab Kernel: Move sys$sigaction() implementation inside ARCH(i386) 2021-02-25 11:33:06 +01:00
Andreas Kling
53c6c29158 Kernel: Tighten some typing in Arch/i386/CPU.h
Use more appropriate types for some things.
2021-02-25 11:32:27 +01:00
Brian Gianforcaro
303620ea85 Kernel: Fix pointer overflow in create_thread
KUBSAN found this overflow from syscall fuzzing.

Fixes #5498
2021-02-24 15:14:13 +01:00
Andreas Kling
ce1775d81d Kernel: Oops, fix broken sys$uname() function definition 2021-02-24 14:42:38 +01:00
Andreas Kling
a48d54dfc5 Kernel: Don't dereference untrusted userspace pointer in sys$uname()
Instead of writing to the userspace utsname struct one field at a time,
build up a utsname on the kernel stack and copy it out to userspace
once it's finished. This is both simpler and gets validity checking
built-in for free.

Found by KUBSAN! :^)

Fixes #5499.
2021-02-24 14:37:36 +01:00
Andreas Kling
5d180d1f99 Everywhere: Rename ASSERT => VERIFY
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)

Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.

We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
2021-02-23 20:56:54 +01:00
Brian Gianforcaro
d934e77522 Kernel: Use copy_n_from_user in sys$setgroups to check for overflow 2021-02-21 17:12:01 +01:00
Brian Gianforcaro
4743afeaf4 Kernel: Use already computed nfds_checked value when copying from user mode.
- We've already computed the number of fds * sizeof(pollfd), so use it
  instead of needlessly doing it again.

- Use fds_copy.data() instead off address of indexing the vector.
2021-02-21 17:12:01 +01:00
Brian Gianforcaro
1c0e2947d7 Kernel: Use copy_n_from_user in sys$setkeymap 2021-02-21 17:12:01 +01:00
Brian Gianforcaro
26bba8e100 Kernel: Populate ELF::AuxilaryValue::Platform from Processor object.
Move this to the processor object so it can easily be implemented
when Serenity is compiled for a different architecture.
2021-02-21 17:06:24 +01:00
Brian Gianforcaro
a977cdd9ac Kernel: Remove unneeded Thread::set_default_signal_dispositions
The `default_signal_action(u8 signal)` function already has the
full mapping. The only caveat being that now we need to make
sure the thread constructor and clear_signals() method do the work
of resetting the m_signal_action_data array, instead or relying on
the previous logic in set_default_signal_dispositions.
2021-02-21 12:54:39 +01:00
Andreas Kling
84b2d4c475 Kernel: Add "map_fixed" pledge promise
This is a new promise that guards access to mmap() with MAP_FIXED.

Fixed-address mappings are rarely used, but can be useful if you are
trying to groom the process address space for malicious purposes.

None of our programs need this at the moment, as the only user of
MAP_FIXED is DynamicLoader, but the fixed mappings are constructed
before the process has had a chance to pledge anything.
2021-02-21 01:08:48 +01:00
Andreas Kling
6e83be67b8 Kernel: Release ptrace lock in exec before stopping due to PT_TRACE_ME
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.
2021-02-19 12:13:54 +01:00
Andreas Kling
eb92ec3149 Kernel: Factor out mmap & friends range expansion to a helper function
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.
2021-02-18 18:04:58 +01:00
Andreas Kling
55a9a4f57a Kernel: Use KResult a bit more in sys$execve() 2021-02-18 09:37:33 +01:00
Andreas Kling
5a595ef134 Kernel: Use dbgln_if() in sys$fork() 2021-02-17 15:34:32 +01:00
Andreas Kling
575c7ed414 Kernel: Make sys$msyscall() EFAULT on non-user address
Fixes #5361.
2021-02-16 11:32:00 +01:00
Ben Wiederhake
fbb85f9b2f Kernel: Refuse excessively long iovec list, also in readv
This bug is a good example why copy-paste code should eventually be eliminated
from the code base: Apparently the code was copied from read.cpp before
c6027ed7cc, so the same bug got introduced here.

To recap: A malicious program can ask the Kernel to prepare sys-ing to
a huge amount of iovecs. The Kernel must first copy all the vector locations
into 'vecs', and before that allocates an arbitrary amount of memory:
    vecs.resize(iov_count);
This can cause Kernel memory exhaustion, triggered by any malicious userland
program.
2021-02-15 22:09:01 +01:00
AnotherTest
4519950266 Kernel+LibC: Add the _SC_GETPW_R_SIZE_MAX sysconf enum
It just returns 4096 :P
2021-02-15 17:32:56 +01:00
AnotherTest
a3a7ab83c4 Kernel+LibC: Implement readv
We already had writev, so let's just add readv too.
2021-02-15 17:32:56 +01:00