From e4d9fa914e28a908ee575d7dabd1b4953bbc5678 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Fri, 22 Jan 2021 18:56:19 +0200 Subject: Kernel: Add base support for VirtRNG (VirtIO based Hardware RNG) This is a very basic implementation that only requests 4096 bytes of entropy from the host once, but its still high quality entropy so it should be a good fix for #4490 (boot-time entropy starvation) for virtualized environments. Co-authored-by: Sahan --- Kernel/CMakeLists.txt | 1 + Kernel/VirtIO/VirtIO.cpp | 5 ++++ Kernel/VirtIO/VirtIORNG.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++ Kernel/VirtIO/VirtIORNG.h | 63 ++++++++++++++++++++++++++++++++++++++ Meta/run.sh | 2 ++ 5 files changed, 144 insertions(+) create mode 100644 Kernel/VirtIO/VirtIORNG.cpp create mode 100644 Kernel/VirtIO/VirtIORNG.h diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 40481e25ee..81230a6b28 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -223,6 +223,7 @@ set(KERNEL_SOURCES VirtIO/VirtIO.cpp VirtIO/VirtIOConsole.cpp VirtIO/VirtIOQueue.cpp + VirtIO/VirtIORNG.cpp VM/AnonymousVMObject.cpp VM/ContiguousVMObject.cpp VM/InodeVMObject.cpp diff --git a/Kernel/VirtIO/VirtIO.cpp b/Kernel/VirtIO/VirtIO.cpp index da787a90da..f11698ebbe 100644 --- a/Kernel/VirtIO/VirtIO.cpp +++ b/Kernel/VirtIO/VirtIO.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace Kernel { @@ -41,6 +42,10 @@ void VirtIO::detect() [[maybe_unused]] auto& unused = adopt(*new VirtIOConsole(address)).leak_ref(); break; } + case VIRTIO_ENTROPY_PCI_DEVICE_ID: { + [[maybe_unused]] auto& unused = adopt(*new VirtIORNG(address)).leak_ref(); + break; + } default: dbgln_if(VIRTIO_DEBUG, "VirtIO: Unknown VirtIO device with ID: {}", id.device_id); break; diff --git a/Kernel/VirtIO/VirtIORNG.cpp b/Kernel/VirtIO/VirtIORNG.cpp new file mode 100644 index 0000000000..91c9348fa4 --- /dev/null +++ b/Kernel/VirtIO/VirtIORNG.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +namespace Kernel { + +VirtIORNG::VirtIORNG(PCI::Address address) + : CharacterDevice(10, 183) + , VirtIODevice(address, "VirtIORNG") +{ + bool success = negotiate_features([&](auto) { + return 0; + }); + if (success) { + success = setup_queues(1); + } + if (success) { + finish_init(); + m_entropy_buffer = MM.allocate_contiguous_kernel_region(PAGE_SIZE, "VirtIORNG", Region::Access::Read | Region::Access::Write); + if (m_entropy_buffer) { + memset(m_entropy_buffer->vaddr().as_ptr(), 0, m_entropy_buffer->size()); + supply_buffer_and_notify(REQUESTQ, ScatterGatherList::create_from_physical(m_entropy_buffer->physical_page(0)->paddr(), m_entropy_buffer->size()), BufferType::DeviceWritable, m_entropy_buffer->vaddr().as_ptr()); + } + } +} + +VirtIORNG::~VirtIORNG() +{ +} + +bool VirtIORNG::handle_device_config_change() +{ + VERIFY_NOT_REACHED(); // Device has no config +} + +void VirtIORNG::handle_queue_update(u16 queue_index) +{ + VERIFY(queue_index == REQUESTQ); + size_t available_entropy = 0; + if (!get_queue(REQUESTQ).get_buffer(&available_entropy)) + return; + dbgln_if(VIRTIO_DEBUG, "VirtIORNG: received {} bytes of entropy!", available_entropy); + for (auto i = 0u; i < available_entropy; i++) { + m_entropy_source.add_random_event(m_entropy_buffer->vaddr().as_ptr()[i]); + } + // TODO: when should we ask for more entropy from the host? +} + +} diff --git a/Kernel/VirtIO/VirtIORNG.h b/Kernel/VirtIO/VirtIORNG.h new file mode 100644 index 0000000000..da2cd3d087 --- /dev/null +++ b/Kernel/VirtIO/VirtIORNG.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +namespace Kernel { + +#define VIRTIO_ENTROPY_PCI_DEVICE_ID 0x1005 + +#define REQUESTQ 0 + +class VirtIORNG final : public CharacterDevice + , public VirtIODevice { +public: + virtual const char* class_name() const override { return m_class_name.characters(); } + + virtual bool can_read(const FileDescription&, size_t) const override { return false; } + virtual KResultOr read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override { return 0; } + virtual bool can_write(const FileDescription&, size_t) const override { return false; } + virtual KResultOr write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override { return 0; } + + virtual mode_t required_mode() const override { return 0666; } + virtual String device_name() const override { return "hwrng"; } + + VirtIORNG(PCI::Address); + virtual ~VirtIORNG() override; + +private: + virtual bool handle_device_config_change() override; + virtual void handle_queue_update(u16 queue_index) override; + + OwnPtr m_entropy_buffer; + EntropySource m_entropy_source; +}; + +} diff --git a/Meta/run.sh b/Meta/run.sh index 10052ec41f..26bbc54ec0 100755 --- a/Meta/run.sh +++ b/Meta/run.sh @@ -57,6 +57,7 @@ $SERENITY_EXTRA_QEMU_ARGS -chardev stdio,id=stdout,mux=on -device virtconsole,chardev=stdout -device isa-debugcon,chardev=stdout +-device virtio-rng-pci -soundhw pcspk -device sb16 " @@ -77,6 +78,7 @@ $SERENITY_EXTRA_QEMU_ARGS -chardev stdio,id=stdout,mux=on -device virtconsole,chardev=stdout -device isa-debugcon,chardev=stdout +-device virtio-rng-pci -soundhw pcspk -device sb16 " -- cgit v1.2.3