1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 19:48:12 +00:00
Commit graph

87 commits

Author SHA1 Message Date
Tom
b17a889320 Kernel: Add safe atomic functions
This allows us to perform atomic operations on potentially unsafe
user space pointers.
2021-01-17 20:30:31 +01:00
asynts
872f2a3b90 Everywhere: Replace a bundle of dbg with dbgln.
These changes are arbitrarily divided into multiple commits to make it
easier to find potentially introduced bugs with git bisect.Everything:
2021-01-11 11:55:47 +01:00
Tom
0d44ee6f2b Kernel: Ignore TLB flush requests for user addresses of other processes
If a TLB flush request is broadcast to other processors and the addresses
to flush are user mode addresses, we can ignore such a request on the
target processor if the page directory currently in use doesn't match
the addresses to be flushed. We still need to broadcast to all processors
in that case because the other processors may switch to that same page
directory at any time.
2021-01-02 20:56:35 +01:00
Linus Groh
bbe787a0af Everywhere: Re-format with clang-format-11
Compared to version 10 this fixes a bunch of formatting issues, mostly
around structs/classes with attributes like [[gnu::packed]], and
incorrect insertion of spaces in parameter types ("T &"/"T &&").
I also removed a bunch of // clang-format off/on and FIXME comments that
are no longer relevant - on the other hand it tried to destroy a couple of
neatly formatted comments, so I had to add some as well.
2020-12-31 21:51:00 +01:00
Luke
865f5ed4f6 Kernel: Prevent sign bit extension when creating a PDPTE
When doing the cast to u64 on the page directory physical address,
the sign bit was being extended. This only beomes an issue when
crossing the 2 GiB boundary. At >= 2 GiB, the physical address
has the sign bit set. For example, 0x80000000.

This set all the reserved bits in the PDPTE, causing a GPF
when loading the PDPT pointer into CR3. The reserved bits are
presumably there to stop you writing out a physical address that
the CPU physically cannot handle, as the size of the reserved bits
is determined by the physical address width of the CPU.

This fixes this by casting to FlatPtr instead. I believe the sign
extension only happens when casting to a bigger type. I'm also using
FlatPtr because it's a pointer we're writing into the PDPTE.
sizeof(FlatPtr) will always be the same size as sizeof(void*).

This also now asserts that the physical address in the PDPTE is
within the max physical address the CPU supports. This is better
than getting a GPF, because CPU::handle_crash tries to do the same
operation that caused the GPF in the first place. That would cause
an infinite loop of GPFs until the stack was exhausted, causing a
triple fault.

As far as I know and tested, I believe we can now use the full 32-bit
physical range without crashing.

Fixes #4584. See that issue for the full debugging story.
2020-12-30 20:33:15 +01:00
Andreas Kling
c25cf5fb56 Kernel: Panic if we're about to switch to a user thread with IOPL!=0
This is a crude protection against IOPL elevation attacks. If for
any reason we find ourselves about to switch to a user mode thread
with IOPL != 0, we'll now simply panic the kernel.

If this happens, it basically means that something tricked the kernel
into incorrectly modifying the IOPL of a thread, so it's no longer
safe to trust the kernel anyway.
2020-12-23 14:30:10 +01:00
Andreas Kling
6bfbc5f5f5 Kernel: Don't allow modifying IOPL via sys$ptrace() or sys$sigreturn()
It was possible to overwrite the entire EFLAGS register since we didn't
do any masking in the ptrace and sigreturn syscalls.

This made it trivial to gain IO privileges by raising IOPL to 3 and
then you could talk to hardware to do all kinds of nasty things.

Thanks to @allesctf for finding these issues! :^)

Their exploit/write-up: https://github.com/allesctf/writeups/blob/master/2020/hxpctf/wisdom2/writeup.md
2020-12-22 19:38:25 +01:00
Tom
da5cc34ebb Kernel: Fix some issues related to fixes and block conditions
Fix some problems with join blocks where the joining thread block
condition was added twice, which lead to a crash when trying to
unblock that condition a second time.

Deferred block condition evaluation by File objects were also not
properly keeping the File object alive, which lead to some random
crashes and corruption problems.

Other problems were caused by the fact that the Queued state didn't
handle signals/interruptions consistently. To solve these issues we
remove this state entirely, along with Thread::wait_on and change
the WaitQueue into a BlockCondition instead.

Also, deliver signals even if there isn't going to be a context switch
to another thread.

Fixes #4336 and #4330
2020-12-12 21:28:12 +01:00
Tom
766db673c1 Kernel: Flush TLBs concurrently
Instead of flushing the TLB on the current processor first and then
notifying the other processors to do the same, notify the others
first, and while waiting on the others flush our own.
2020-12-02 23:49:52 +01:00
Tom
78f1b5e359 Kernel: Fix some problems with Thread::wait_on and Lock
This changes the Thread::wait_on function to not enable interrupts
upon leaving, which caused some problems with page fault handlers
and in other situations. It may now be called from critical
sections, with interrupts enabled or disabled, and returns to the
same state.

This also requires some fixes to Lock. To aid debugging, a new
define LOCK_DEBUG is added that enables checking for Lock leaks
upon finalization of a Thread.
2020-12-01 09:48:34 +01:00
Tom
3ee7c21fae Kernel: Implement capturing stack trace on a different CPU
When trying to get a stack trace of a thread on another CPU we send
a SMP message to that processor to capture the stack trace for us.
2020-11-11 12:27:25 +01:00
Tom
e26e0445b5 Kernel: Make m_halt_requested an atomic variable
We need to make sure the change to this variable is visible to all
processors instantly.
2020-11-11 12:27:25 +01:00
Tom
b9a97ff81f Kernel: Add mechanism to queue deferred function calls
Function calls that are deferred will be executed before a thread
enters a pre-emptable state (meaning it is not in a critical section
and it is not in an irq handler). If it is not already in such a
state, it will be called immediately.

This is meant to be used from e.g. IRQ handlers where we might want
to block a thread until an interrupt happens.
2020-11-04 21:21:37 +01:00
Lenny Maiorani
d1fe6a0b53
Everywhere: Redundant inline specifier on constexpr functions (#3807)
Problem:
- `constexpr` functions are decorated with the `inline` specifier
  keyword. This is redundant because `constexpr` functions are
  implicitly `inline`.
- [dcl.constexpr], §7.1.5/2 in the C++11 standard): "constexpr
  functions and constexpr constructors are implicitly inline (7.1.2)".

Solution:
- Remove the redundant `inline` keyword.
2020-10-20 18:08:13 +02:00
Nico Weber
8a01be4849 Kernel: Add some CPU feature flags related to TSC
In case we want to rely more on TSC in time keeping in the future, idk

This adds:

- RDTSCP, for when the RDTSCP instruction is available

- CONSTANT_TSC, for when the TSC has a constant frequency, invariant
  under things like the CPU boosting its frequency.

- NONSTOP_TSC, for when the TSC doesn't pause when the CPU enters
  sleep states.

AMD cpus and newer intel cpus set the INVSTC bit (bit 8 in edx of
extended cpuid 0x8000000008), which implies both CONSTANT_TSC and
NONSTOP_TSC. Some older intel processors have CONSTANT_TSC but not
NONSTOP_TSC; this is set based on cpu model checks.

There isn't a ton of documentation on this, so this follows Linux
terminology and http://blog.tinola.com/?e=54

CONSTANT_TSC:
39b3a79105

NONSTOP_TSC:
40fb17152c

qemu disables invtsc (bit 8 in edx of extended cpuid 0x8000000008)
by default even if the host cpu supports it. It can be enabled by
running with `SERENITY_QEMU_CPU=host,migratable=off` set.
2020-10-08 10:00:39 +02:00
Tom
7d1b8417bd Kernel: Add safe_memcpy, safe_memset and safe_strnlen
These special functions can be used to safely copy/set memory or
determine the length of a string, e.g. provided by user mode.

In the event of a page fault, safe_memcpy/safe_memset will return
false and safe_strnlen will return -1.
2020-09-13 21:19:15 +02:00
Luke
8a2fd0e436 Kernel: Fix Processor::features_string() stopping too early and detect more features
The exit condition for the loop was sizeof(m_features) * 8,
which was 32. Presumably this was supposed to mean 32 bits, but it
actually made it stop as soon as it reached the 6th bit.

Also add detection for more SIMD CPU features.
2020-08-31 18:57:54 +02:00
Tom
67dbb56444 Kernel: Release page tables when no longer needed
When unmapping regions, check if page tables can be freed.

This is a follow-up change for #3254.
2020-08-28 09:21:24 +02:00
Tom
728de56481 Kernel: Prevent recursive calls into the scheduler
Upon leaving a critical section (such as a SpinLock) we need to
check if we're already asynchronously invoking the Scheduler.
Otherwise we might end up triggering another context switch
as soon as leaving the scheduler lock.

Fixes #2883
2020-08-02 17:15:11 +02:00
Nico Weber
4eb967b5eb LibC+Kernel: Start implementing sysconf
For now, only the non-standard _SC_NPROCESSORS_CONF and
_SC_NPROCESSORS_ONLN are implemented.

Use them to make ninja pick a better default -j value.
While here, make the ninja package script not fail if
no other port has been built yet.
2020-07-15 00:07:20 +02:00
Tom
ce5ae83963 Kernel: Detect syscall/sysenter support 2020-07-08 23:47:36 +02:00
Tom
bc107d0b33 Kernel: Add SMP IPI support
We can now properly initialize all processors without
crashing by sending SMP IPI messages to synchronize memory
between processors.

We now initialize the APs once we have the scheduler running.
This is so that we can process IPI messages from the other
cores.

Also rework interrupt handling a bit so that it's more of a
1:1 mapping. We need to allocate non-sharable interrupts for
IPIs.

This also fixes the occasional hang/crash because all
CPUs now synchronize memory with each other.
2020-07-06 17:07:44 +02:00
Andreas Kling
163c9d5f8f Kernel: Thread::wait_on() must always leave interrupts enabled on exit
The short-circuit path added for waiting on a queue that already had a
pending wake was able to return with interrupts disabled, which breaks
the API contract of wait_on() always returning with IF=1.

Fix this by adding a way to override the restored IF in ScopedCritical.
2020-07-06 11:33:32 +02:00
Andreas Kling
3e0020e67d Kernel: Tidy up the ScopedCritical class a little bit 2020-07-06 11:33:32 +02:00
Tom
2a82a25fec Kernel: Various context switch fixes
These changes solve a number of problems with the software
context swithcing:

* The scheduler lock really should be held throughout context switches
* Transitioning from the initial (idle) thread to another needs to
  hold the scheduler lock
* Transitioning from a dying thread to another also needs to hold
  the scheduler lock
* Dying threads cannot necessarily be finalized if they haven't
  switched out of it yet, so flag them as active while a processor
  is running it (the Running state may be switched to Dying while
  it still is actually running)
2020-07-06 10:00:24 +02:00
Tom
bb84fad0bf Kernel: Fix retreiving frame pointer from a thread
If we're trying to walk the stack for another thread, we can
no longer retreive the EBP register from Thread::m_tss. Instead,
we need to look at the top of the kernel stack, because all threads
not currently running were last in kernel mode. Context switches
now always trigger a brief switch to kernel mode, and Thread::m_tss
only is used to save ESP and EIP.

Fixes #2678
2020-07-03 21:16:56 +02:00
Tom
9b4e6f6a23 Kernel: Consolidate features into CPUFeature enum
This allows us to consolidate printing out all the CPU features
into one log statement. Also expose them in /proc/cpuinfo
2020-07-03 19:32:34 +02:00
Tom
e373e5f007 Kernel: Fix signal delivery
When delivering urgent signals to the current thread
we need to check if we should be unblocked, and if not
we need to yield to another process.

We also need to make sure that we suppress context switches
during Process::exec() so that we don't clobber the registers
that it sets up (eip mainly) by a context switch. To be able
to do that we add the concept of a critical section, which are
similar to Process::m_in_irq but different in that they can be
requested at any time. Calls to Scheduler::yield and
Scheduler::donate_to will return instantly without triggering
a context switch, but the processor will then asynchronously
trigger a context switch once the critical section is left.
2020-07-03 19:32:34 +02:00
Tom
57b61b2dde Kernel: Split initialization of Processor structure
We need to very early on initialize the Processor structure so
that we can use RecursiveSpinLock early on.
2020-07-03 19:32:34 +02:00
Tom
2a38cc9a12 Kernel: Add a quickmap region for each processor
Threads need to be able to concurrently quickmap things.
2020-07-01 12:07:01 +02:00
Tom
16783bd14d Kernel: Turn Thread::current and Process::current into functions
This allows us to query the current thread and process on a
per processor basis
2020-07-01 12:07:01 +02:00
Tom
d98edb3171 Kernel: List all CPUs in /proc/cpuinfo 2020-07-01 12:07:01 +02:00
Tom
fb41d89384 Kernel: Implement software context switching and Processor structure
Moving certain globals into a new Processor structure for
each CPU allows us to eventually run an instance of the
scheduler on each CPU.
2020-07-01 12:07:01 +02:00
3541
4fa6301523 Kernel: Add g_cpu_supports_rdseed
CPUs which support RDRAND do not necessarily support RDSEED. This
introduces a flag g_cpu_supports_rdseed which is set appropriately
by CPUID. This causes Haswell CPUs in particular (and probably a lot
of AMD chips) to now fail to boot with #2634, rather than an illegal
instruction.

It seems like the KernelRng needs either an initial reseed call or
more random events added before the first call to get_good_random,
but I don't feel qualified to make that kind of change.
2020-06-27 12:57:03 +02:00
Tom
0bc92c259d Kernel: Detect APs and boot them into protected mode
This isn't fully working, the APs pretend like they're
fully initialized and are just halted permanently for now.
2020-06-04 18:15:23 +02:00
Andreas Kling
81d35c6891 Kernel: Always inline stac(), clac() and SmapDisabler
Let's not be paying the function call overhead for these tiny ops.
Maybe there's an argument for having fewer gadgets in the kernel but
for now we're actually seeing stac() in profiles so let's put
that above theoretical security issues.
2020-05-20 14:17:01 +02:00
Andreas Kling
21d5f4ada1 Kernel: Absorb LibBareMetal back into the kernel
This was supposed to be the foundation for some kind of pre-kernel
environment, but nobody is working on it right now, so let's move
everything back into the kernel and remove all the confusion.
2020-05-16 12:00:04 +02:00
Andreas Kling
6fe83b0ac4 Kernel: Crash the current process on OOM (instead of panicking kernel)
This patch adds PageFaultResponse::OutOfMemory which informs the fault
handler that we were unable to allocate a necessary physical page and
cannot continue.

In response to this, the kernel will crash the current process. Because
we are OOM, we can't symbolicate the crash like we normally would
(since the ELF symbolication code needs to allocate), so we also
communicate to Process::crash() that we're out of memory.

Now we can survive "allocate 300 MB" (only the allocate process dies.)
This is definitely not perfect and can easily end up killing a random
innocent other process who happened to allocate one page at the wrong
time, but it's a *lot* better than panicking on OOM. :^)
2020-05-06 22:28:23 +02:00
Itamar
d04409b444 CPU: Handle Debug exception
We currently only care about debug exceptions that are triggered
by the single-step execution mode.

The debug exception is translated to a SIGTRAP, which can be caught
and handled by the tracing thread.
2020-04-13 23:20:59 +02:00
Liav A
9a303cc5a5 Kernel: Add the NonMaskableInterruptDisabler class
This class will be used later to disable NMIs when we
initialize the RTC timer.
2020-03-19 15:48:00 +01:00
Andreas Kling
b1058b33fb AK: Add global FlatPtr typedef. It's u32 or u64, based on sizeof(void*)
Use this instead of uintptr_t throughout the codebase. This makes it
possible to pass a FlatPtr to something that has u32 and u64 overloads.
2020-03-08 13:06:51 +01:00
Liav A
b41e2d25b4 CPU: Use dbg() instead of dbgprintf() 2020-02-27 13:05:12 +01:00
Liav A
bb73802b15 CPU: Use the new interrupt components
Now we use the GenericInterruptHandler class instead of IRQHandler in
the CPU functions.
This commit adds an include to the ISR stub macros header file.
Also, this commit adds support for IRQ sharing, so when an IRQHandler
will try to register to already-assigned IRQ number, a SharedIRQHandler
will be created to register both IRQHandlers.
2020-02-24 11:27:03 +01:00
Andreas Kling
59b9e49bcd Kernel: Don't trigger page faults during profiling stack walk
The kernel sampling profiler will walk thread stacks during the timer
tick handler. Since it's not safe to trigger page faults during IRQ's,
we now avoid this by checking the page tables manually before accessing
each stack location.
2020-02-21 15:49:39 +01:00
Andreas Kling
d46071c08f Kernel: Assert on page fault during IRQ
We're not equipped to deal with page faults during an IRQ handler,
so add an assertion so we can immediately tell what's wrong.

This is why profiling sometimes hangs the system -- walking the stack
of the profiled thread causes a page fault and things fall apart.
2020-02-21 15:49:34 +01:00
Andreas Kling
a356e48150 Kernel: Move all code into the Kernel namespace 2020-02-16 01:27:42 +01:00
Andreas Kling
0341ddc5eb Kernel: Rename RegisterDump => RegisterState 2020-02-16 00:15:37 +01:00
Andreas Kling
27f0102bbe Kernel: Add getter and setter for the X86 CR3 register
This gets rid of a bunch of inline assembly.
2020-02-10 20:00:32 +01:00
Andreas Kling
ccfee3e573 Kernel: Remove more <LibBareMetal/Output/kstdio.h> includes 2020-02-10 12:07:48 +01:00
Liav A
99ea80695e Kernel: Use VirtualAddress & PhysicalAddress classes from LibBareMetal 2020-02-09 19:38:17 +01:00