From 34e92438724cdb062dae1765fc7e765b44f51ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sat, 19 Nov 2022 18:28:19 +0100 Subject: [PATCH] random: always use the PRNG, and use entropy sources to feed it remove the yarrow module. the hardware modules can push entropy with queue_randomness(). virtio_rng will now push entropy every 300 seconds. helps with #14937 Change-Id: If76c5deabf61dc616a0e051332f44b89deb6b8a1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5824 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- headers/private/drivers/random.h | 10 +- .../kernel/bus_managers/random/driver.cpp | 56 +++------ .../kernel/bus_managers/random/yarrow_rng.cpp | 75 ++++------- .../kernel/bus_managers/random/yarrow_rng.h | 16 ++- .../kernel/busses/random/VirtioRNGDevice.cpp | 114 ++++++++++------- .../kernel/busses/random/VirtioRNGPrivate.h | 20 ++- .../kernel/busses/random/virtio_rng.cpp | 116 +++--------------- .../kernel/device_manager/device_manager.cpp | 2 +- 8 files changed, 157 insertions(+), 252 deletions(-) diff --git a/headers/private/drivers/random.h b/headers/private/drivers/random.h index cc4d1d5174..55de3dcc2b 100644 --- a/headers/private/drivers/random.h +++ b/headers/private/drivers/random.h @@ -14,18 +14,12 @@ typedef struct { driver_module_info info; + + status_t (*queue_randomness)(uint64 value); } random_for_controller_interface; #define RANDOM_FOR_CONTROLLER_MODULE_NAME "bus_managers/random/controller/driver_v1" -// Bus manager interface used by Random controller drivers. -typedef struct random_module_info { - driver_module_info info; - - status_t (*read)(void* cookie, void *_buffer, size_t *_numBytes); - status_t (*write)(void* cookie, const void *_buffer, size_t *_numBytes); -} random_module_info; - #endif /* _RANDOM_H */ diff --git a/src/add-ons/kernel/bus_managers/random/driver.cpp b/src/add-ons/kernel/bus_managers/random/driver.cpp index 8e0d87fb8f..d5486f5e1f 100644 --- a/src/add-ons/kernel/bus_managers/random/driver.cpp +++ b/src/add-ons/kernel/bus_managers/random/driver.cpp @@ -34,7 +34,6 @@ static mutex sRandomLock; -static random_module_info *sRandomModule; static void *sRandomCookie; device_manager_info* gDeviceManager; @@ -44,6 +43,15 @@ typedef struct { } random_driver_info; +static status_t +random_queue_randomness(uint64 value) +{ + MutexLocker locker(&sRandomLock); + RANDOM_ENQUEUE(value); + return B_OK; +} + + // #pragma mark - device module API @@ -74,7 +82,7 @@ random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes) TRACE("read(%Ld,, %ld)\n", position, *_numBytes); MutexLocker locker(&sRandomLock); - return sRandomModule->read(sRandomCookie, _buffer, _numBytes); + return RANDOM_READ(sRandomCookie, _buffer, _numBytes); } @@ -83,11 +91,7 @@ random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes { TRACE("write(%Ld,, %ld)\n", position, *_numBytes); MutexLocker locker(&sRandomLock); - if (sRandomModule->write == NULL) { - *_numBytes = 0; - return EINVAL; - } - return sRandomModule->write(sRandomCookie, buffer, _numBytes); + return RANDOM_WRITE(sRandomCookie, buffer, _numBytes); } @@ -187,6 +191,7 @@ random_init_driver(device_node *node, void **cookie) return B_NO_MEMORY; mutex_init(&sRandomLock, "/dev/random lock"); + RANDOM_INIT(); memset(info, 0, sizeof(*info)); @@ -202,6 +207,8 @@ random_uninit_driver(void *_cookie) { CALLED(); + RANDOM_UNINIT(); + mutex_destroy(&sRandomLock); random_driver_info* info = (random_driver_info*)_cookie; @@ -220,38 +227,10 @@ random_register_child_devices(void* _cookie) gDeviceManager->publish_device(info->node, "urandom", RANDOM_DEVICE_MODULE_NAME); } - - // add the default Yarrow RNG - device_attr attrs[] = { - { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, - { string: "Yarrow RNG" }}, - { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, - { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }}, - { NULL } - }; - - device_node* node; - return gDeviceManager->register_node(info->node, - YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node); -} - - -// #pragma mark - - - -status_t -random_added_device(device_node *node) -{ - CALLED(); - - status_t status = gDeviceManager->get_driver(node, - (driver_module_info **)&sRandomModule, &sRandomCookie); - return status; } - // #pragma mark - @@ -311,11 +290,13 @@ random_for_controller_interface sRandomForControllerModule = { }, NULL, // supported devices - random_added_device, + NULL, NULL, NULL, NULL - } + }, + + random_queue_randomness, }; @@ -323,6 +304,5 @@ module_info* modules[] = { (module_info*)&sRandomDriver, (module_info*)&sRandomDevice, (module_info*)&sRandomForControllerModule, - (module_info*)&gYarrowRandomModule, NULL }; diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp index 129f07c378..0716dc8825 100644 --- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp +++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp @@ -286,10 +286,28 @@ kill_chrand(ch_randgen *randgen) // #pragma mark - -// Random interface -static status_t +status_t +yarrow_init() +{ + CALLED(); + sRandomEnv = new_chrand(8); + if (sRandomEnv == NULL) + return B_NO_MEMORY; + return B_OK; +} + + +void +yarrow_uninit() +{ + CALLED(); + kill_chrand(sRandomEnv); +} + + +status_t yarrow_rng_read(void* cookie, void *_buffer, size_t *_numBytes) { if (!IS_USER_ADDRESS(_buffer)) @@ -323,7 +341,7 @@ yarrow_rng_read(void* cookie, void *_buffer, size_t *_numBytes) } -static status_t +status_t yarrow_rng_write(void* cookie, const void *_buffer, size_t *_numBytes) { OCTET *buffer = (OCTET*)_buffer; @@ -342,54 +360,9 @@ yarrow_rng_write(void* cookie, const void *_buffer, size_t *_numBytes) } -// #pragma mark - - - -static status_t -yarrow_init_bus(device_node* node, void** bus_cookie) +void +yarrow_enqueue_randomness(const uint64 value) { CALLED(); - sRandomEnv = new_chrand(8); - if (sRandomEnv == NULL) - return B_NO_MEMORY; - return B_OK; + chseed(sRandomEnv, value); } - - -static void -yarrow_uninit_bus(void* bus_cookie) -{ - CALLED(); - kill_chrand(sRandomEnv); -} - - -static void -yarrow_bus_removed(void* bus_cookie) -{ - return; -} - - -// #pragma mark - - - -random_module_info gYarrowRandomModule = { - { - { - YARROW_RNG_SIM_MODULE_NAME, - 0, - NULL - }, - - NULL, // supports_device, - NULL, // register_device, - yarrow_init_bus, - yarrow_uninit_bus, - NULL, // register child devices - NULL, // rescan - yarrow_bus_removed, - }, - yarrow_rng_read, - yarrow_rng_write -}; diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.h b/src/add-ons/kernel/bus_managers/random/yarrow_rng.h index b76f3145e9..b90f66e880 100644 --- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.h +++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.h @@ -14,15 +14,23 @@ #include "random.h" -#define YARROW_RNG_SIM_MODULE_NAME "bus_managers/random/yarrow_rng/device/v1" - - #ifdef __cplusplus extern "C" { #endif +status_t yarrow_init(); +void yarrow_uninit(); +void yarrow_enqueue_randomness(const uint64 value); -extern random_module_info gYarrowRandomModule; +status_t yarrow_rng_read(void* cookie, void *_buffer, size_t *_numBytes); +status_t yarrow_rng_write(void* cookie, const void *_buffer, size_t *_numBytes); + + +#define RANDOM_INIT yarrow_init +#define RANDOM_UNINIT yarrow_uninit +#define RANDOM_ENQUEUE yarrow_enqueue_randomness +#define RANDOM_READ yarrow_rng_read +#define RANDOM_WRITE yarrow_rng_write #ifdef __cplusplus diff --git a/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp index 06f3d7cda9..256bde1c2c 100644 --- a/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp +++ b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp @@ -24,24 +24,19 @@ get_feature_name(uint32 feature) VirtioRNGDevice::VirtioRNGDevice(device_node *node) : - fNode(node), fVirtio(NULL), fVirtioDevice(NULL), fStatus(B_NO_INIT), - fOffset(BUFFER_SIZE), - fExpectsInterrupt(false) + fExpectsInterrupt(false), + fDPCHandle(NULL) { CALLED(); B_INITIALIZE_SPINLOCK(&fInterruptLock); fInterruptCondition.Init(this, "virtio rng transfer"); - get_memory_map(fBuffer, BUFFER_SIZE, &fEntry, 1); - // get the Virtio device from our parent's parent - device_node *parent = gDeviceManager->get_parent_node(node); - device_node *virtioParent = gDeviceManager->get_parent_node(parent); - gDeviceManager->put_node(parent); + device_node *virtioParent = gDeviceManager->get_parent_node(node); gDeviceManager->get_driver(virtioParent, (driver_module_info **)&fVirtio, (void **)&fVirtioDevice); @@ -68,11 +63,31 @@ VirtioRNGDevice::VirtioRNGDevice(device_node *node) ERROR("queue interrupt setup failed (%s)\n", strerror(fStatus)); return; } + + fStatus = gDPC->new_dpc_queue(&fDPCHandle, "virtio_rng timer", + B_LOW_PRIORITY); + if (fStatus != B_OK) { + ERROR("dpc setup failed (%s)\n", strerror(fStatus)); + return; + } + + if (fStatus == B_OK) { + fTimer.user_data = this; + fStatus = add_timer(&fTimer, &HandleTimerHook, 300 * 1000 * 1000, B_PERIODIC_TIMER); + if (fStatus != B_OK) + ERROR("timer setup failed (%s)\n", strerror(fStatus)); + } + + // trigger also now + gDPC->queue_dpc(fDPCHandle, HandleDPC, this); } VirtioRNGDevice::~VirtioRNGDevice() { + cancel_timer(&fTimer); + gDPC->delete_dpc_queue(fDPCHandle); + } @@ -84,46 +99,42 @@ VirtioRNGDevice::InitCheck() status_t -VirtioRNGDevice::Read(void* _buffer, size_t* _numBytes) +VirtioRNGDevice::_Enqueue() { CALLED(); - if (fOffset >= BUFFER_SIZE) { - { - InterruptsSpinLocker locker(fInterruptLock); - fExpectsInterrupt = true; - fInterruptCondition.Add(&fInterruptConditionEntry); - } - status_t result = fVirtio->queue_request(fVirtioQueue, NULL, &fEntry, - NULL); - if (result != B_OK) { - ERROR("queueing failed (%s)\n", strerror(result)); - return result; - } + uint64 value = 0; + physical_entry entry; + get_memory_map(&value, sizeof(value), &entry, 1); - result = fInterruptConditionEntry.Wait(B_CAN_INTERRUPT); - - { - InterruptsSpinLocker locker(fInterruptLock); - fExpectsInterrupt = false; - } - - if (result == B_OK) { - fOffset = 0; - } else if (result != B_INTERRUPTED) { - ERROR("request failed (%s)\n", strerror(result)); - } + { + InterruptsSpinLocker locker(fInterruptLock); + fExpectsInterrupt = true; + fInterruptCondition.Add(&fInterruptConditionEntry); + } + status_t result = fVirtio->queue_request(fVirtioQueue, NULL, &entry, NULL); + if (result != B_OK) { + ERROR("queueing failed (%s)\n", strerror(result)); + return result; } - if (fOffset < BUFFER_SIZE) { - size_t size = min_c(BUFFER_SIZE - fOffset, *_numBytes); - if (user_memcpy(_buffer, fBuffer + fOffset, size) != B_OK) - return B_BAD_ADDRESS; - fOffset += size; - *_numBytes = size; - } else - *_numBytes = 0; - return B_OK; + result = fInterruptConditionEntry.Wait(B_CAN_INTERRUPT); + + { + InterruptsSpinLocker locker(fInterruptLock); + fExpectsInterrupt = false; + } + + if (result == B_OK) { + if (value != 0) { + gRandom->queue_randomness(value); + TRACE("enqueue %" B_PRIx64 "\n", value); + } + } else if (result != B_OK && result != B_INTERRUPTED) { + ERROR("request failed (%s)\n", strerror(result)); + } + + return result; } @@ -145,3 +156,22 @@ VirtioRNGDevice::_RequestInterrupt() SpinLocker locker(fInterruptLock); fInterruptCondition.NotifyAll(); } + + +/*static*/ int32 +VirtioRNGDevice::HandleTimerHook(struct timer* timer) +{ + VirtioRNGDevice* device = reinterpret_cast(timer->user_data); + + gDPC->queue_dpc(device->fDPCHandle, HandleDPC, device); + return B_HANDLED_INTERRUPT; +} + + +/*static*/ void +VirtioRNGDevice::HandleDPC(void *arg) +{ + VirtioRNGDevice* device = reinterpret_cast(arg); + device->_Enqueue(); +} + diff --git a/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h index 60a4921ee8..66ffaa395c 100644 --- a/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h +++ b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h @@ -7,6 +7,7 @@ #include +#include #include #include "random.h" #include @@ -24,9 +25,7 @@ extern device_manager_info* gDeviceManager; extern random_for_controller_interface *gRandom; - - -#define BUFFER_SIZE 16 +extern dpc_module_info *gDPC; class VirtioRNGDevice { @@ -36,15 +35,15 @@ public: status_t InitCheck(); - status_t Read(void* buffer, size_t* numBytes); - +protected: + static int32 HandleTimerHook(struct timer* timer); + static void HandleDPC(void* arg); private: static void _RequestCallback(void* driverCookie, void *cookie); void _RequestInterrupt(); - - device_node* fNode; + status_t _Enqueue(); virtio_device_interface* fVirtio; virtio_device* fVirtioDevice; @@ -53,14 +52,13 @@ private: uint32 fFeatures; ::virtio_queue fVirtioQueue; - physical_entry fEntry; - uint8 fBuffer[BUFFER_SIZE]; - uint32 fOffset; - spinlock fInterruptLock; ConditionVariable fInterruptCondition; ConditionVariableEntry fInterruptConditionEntry; bool fExpectsInterrupt; + + timer fTimer; + void* fDPCHandle; }; diff --git a/src/add-ons/kernel/busses/random/virtio_rng.cpp b/src/add-ons/kernel/busses/random/virtio_rng.cpp index 951c4eb149..54ee834a3f 100644 --- a/src/add-ons/kernel/busses/random/virtio_rng.cpp +++ b/src/add-ons/kernel/busses/random/virtio_rng.cpp @@ -19,47 +19,7 @@ device_manager_info *gDeviceManager; random_for_controller_interface *gRandom; - - -// #pragma mark - Random module interface - - -static status_t -sim_init_bus(device_node *node, void **_cookie) -{ - CALLED(); - - VirtioRNGDevice *device = new(std::nothrow) - VirtioRNGDevice(node); - if (device == NULL) - return B_NO_MEMORY; - status_t status = device->InitCheck(); - if (status < B_OK) { - delete device; - return status; - } - - *_cookie = device; - return B_OK; -} - - -static void -sim_uninit_bus(void *cookie) -{ - CALLED(); - VirtioRNGDevice *device = (VirtioRNGDevice*)cookie; - - delete device; -} - - -static status_t -sim_read(void* cookie, void *_buffer, size_t *_numBytes) -{ - VirtioRNGDevice *device = (VirtioRNGDevice*)cookie; - return device->Read(_buffer, _numBytes); -} +dpc_module_info *gDPC; // #pragma mark - Driver module interface @@ -107,77 +67,39 @@ static status_t virtio_rng_init_driver(device_node *node, void **_cookie) { CALLED(); - *_cookie = node; + VirtioRNGDevice *device = new(std::nothrow) VirtioRNGDevice(node); + if (device == NULL) + return B_NO_MEMORY; + status_t status = device->InitCheck(); + if (status < B_OK) { + delete device; + return status; + } + *_cookie = device; + return B_OK; } -static status_t -virtio_rng_register_child_devices(void *cookie) +static void +virtio_rng_uninit_driver(void *cookie) { - CALLED(); - device_node *node = (device_node *)cookie; - - device_attr attrs[] = { - { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, - { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }}, - { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, - { string: VIRTIO_RNG_CONTROLLER_PRETTY_NAME }}, - { NULL } - }; - - return gDeviceManager->register_node(node, - VIRTIO_RNG_DEVICE_MODULE_NAME, attrs, NULL, NULL); + VirtioRNGDevice *device = (VirtioRNGDevice*)cookie; + delete device; } -static status_t -std_ops(int32 op, ...) -{ - switch (op) { - case B_MODULE_INIT: - case B_MODULE_UNINIT: - return B_OK; - - default: - return B_ERROR; - } -} - - -static random_module_info sVirtioRNGDeviceInterface = { - { - { - VIRTIO_RNG_DEVICE_MODULE_NAME, - 0, - std_ops - }, - NULL, // supported devices - NULL, // register node - sim_init_bus, - sim_uninit_bus, - NULL, // register child devices - NULL, // rescan - NULL // bus_removed - }, - - sim_read, - NULL // write - -}; - - static driver_module_info sVirtioRNGDriver = { { VIRTIO_RNG_DRIVER_MODULE_NAME, 0, - std_ops + NULL }, virtio_rng_supports_device, virtio_rng_register_device, virtio_rng_init_driver, - NULL, // uninit_driver, - virtio_rng_register_child_devices, + virtio_rng_uninit_driver, + NULL, NULL, // rescan NULL, // device_removed }; @@ -186,12 +108,12 @@ static driver_module_info sVirtioRNGDriver = { module_dependency module_dependencies[] = { { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, { RANDOM_FOR_CONTROLLER_MODULE_NAME, (module_info **)&gRandom }, + { B_DPC_MODULE_NAME, (module_info **)&gDPC }, {} }; module_info *modules[] = { (module_info *)&sVirtioRNGDriver, - (module_info *)&sVirtioRNGDeviceInterface, NULL }; diff --git a/src/system/kernel/device_manager/device_manager.cpp b/src/system/kernel/device_manager/device_manager.cpp index 22365e1d45..a5b99712f6 100644 --- a/src/system/kernel/device_manager/device_manager.cpp +++ b/src/system/kernel/device_manager/device_manager.cpp @@ -1743,6 +1743,7 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path) _AddPath(*stack, "bus_managers"); } else if (!generic) { _AddPath(*stack, "drivers"); + _AddPath(*stack, "busses/virtio"); } else { // For generic drivers, we only allow busses when the // request is more specified @@ -1756,7 +1757,6 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path) _AddPath(*stack, "busses/i2c"); _AddPath(*stack, "busses/scsi"); _AddPath(*stack, "busses/random"); - _AddPath(*stack, "busses/virtio"); _AddPath(*stack, "bus_managers/pci"); } break;