Pārlūkot izejas kodu

Kernel: Make use of interrupts as an entropy source

Booting old computers without RDRAND/RDSEED and without a disk makes
the system severely starved for entropy. Uses interrupts as a source
to side-step that issue.

Also warn whenever the system is starved of entropy, because that's
a non-obvious failure mode.
Jean-Baptiste Boric 4 gadi atpakaļ
vecāks
revīzija
7eaefa5aa6
3 mainītis faili ar 16 papildinājumiem un 2 dzēšanām
  1. 4 0
      Kernel/Arch/i386/CPU.cpp
  2. 2 1
      Kernel/Random.cpp
  3. 10 1
      Kernel/Random.h

+ 4 - 0
Kernel/Arch/i386/CPU.cpp

@@ -44,6 +44,7 @@
 #include <Kernel/Interrupts/UnhandledInterruptHandler.h>
 #include <Kernel/KSyms.h>
 #include <Kernel/Process.h>
+#include <Kernel/Random.h>
 #include <Kernel/SpinLock.h>
 #include <Kernel/Thread.h>
 #include <Kernel/VM/MemoryManager.h>
@@ -58,6 +59,8 @@ static Descriptor s_idt[256];
 
 static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_COUNT];
 
+static EntropySource s_entropy_source_interrupts{EntropySource::Static::Interrupts};
+
 // The compiler can't see the calls to these functions inside assembly.
 // Declare them, to avoid dead code warnings.
 extern "C" void enter_thread_context(Thread* from_thread, Thread* to_thread);
@@ -709,6 +712,7 @@ void handle_interrupt(TrapFrame* trap)
     auto& regs = *trap->regs;
     ASSERT(regs.isr_number >= IRQ_VECTOR_BASE && regs.isr_number <= (IRQ_VECTOR_BASE + GENERIC_INTERRUPT_HANDLERS_COUNT));
     u8 irq = (u8)(regs.isr_number - 0x50);
+    s_entropy_source_interrupts.add_random_event(irq);
     auto* handler = s_interrupt_handler[irq];
     ASSERT(handler);
     handler->increment_invoking_counter();

+ 2 - 1
Kernel/Random.cpp

@@ -69,6 +69,7 @@ KernelRng::KernelRng()
 void KernelRng::wait_for_entropy()
 {
     if (!resource().is_ready()) {
+        dbgln("Entropy starvation...");
         m_seed_queue.wait_on({}, "KernelRng");
     }
 }
@@ -80,7 +81,7 @@ void KernelRng::wake_if_ready()
     }
 }
 
-size_t EntropySource::next_source { 0 };
+size_t EntropySource::next_source { static_cast<size_t>(EntropySource::Static::MaxHardcodedSourceIndex) };
 
 void get_good_random_bytes(u8* buffer, size_t buffer_size)
 {

+ 10 - 1
Kernel/Random.h

@@ -147,11 +147,21 @@ class EntropySource {
     };
 
 public:
+    enum class Static : size_t {
+        Interrupts,
+        MaxHardcodedSourceIndex,
+    };
+
     EntropySource()
         : m_source(next_source++)
     {
     }
 
+    EntropySource(Static hardcoded_source)
+        : m_source(static_cast<size_t>(hardcoded_source))
+    {
+    }
+
     template<typename T>
     void add_random_event(const T& event_data)
     {
@@ -166,7 +176,6 @@ private:
     static size_t next_source;
     size_t m_pool { 0 };
     size_t m_source;
-    Lock m_lock;
 };
 
 // NOTE: These API's are primarily about expressing intent/needs in the calling code.