From 7e4e0926533de4ecbd439b7f449a6e77c25b1145 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Sun, 13 Oct 2019 11:41:55 -0300 Subject: [PATCH] Kernel: Add a Linux-style getrandom syscall The way it gets the entropy and blasts it to the buffer is pretty ugly IMHO, but it does work for now. (It should be replaced, by not truncating a u32.) It implements an (unused for now) flags argument, like Linux but instead of OpenBSD's. This is in case we want to distinguish between entropy sources or any other reason and have to implement a new syscall later. Of course, learn from Linux's struggles with entropy sourcing too. --- Kernel/Process.cpp | 21 +++++++++++++++++++++ Kernel/Process.h | 1 + Kernel/Syscall.cpp | 2 ++ Kernel/Syscall.h | 3 ++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 8a122fb1db..ed70fc25b7 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -3076,3 +3077,23 @@ int Process::sys$get_process_name(char* buffer, int buffer_size) strncpy(buffer, m_name.characters(), buffer_size); return 0; } + +// We don't use the flag yet, but we could use it for distinguishing +// random source like Linux, unlike the OpenBSD equivalent. However, if we +// do, we should be able of the caveats that Linux has dealt with. +int Process::sys$getrandom(void* buffer, size_t buffer_size, unsigned int flags __attribute__((unused))) +{ + if (buffer_size <= 0) + return -EINVAL; + + if (!validate_write(buffer, buffer_size)) + return -EFAULT; + // XXX: We probably lose a lot of entropy here, out of an already marginal + // PRNG. A better implementation would not throw away bits for the sake of + // array indexing, and use a better PRNG in the first place. + uint8_t* bytes = (uint8_t*)buffer; + for (size_t i = 0; i < buffer_size; i++) + bytes[i] = (uint8_t)(RandomDevice::random_value() % 255); + + return 0; +} diff --git a/Kernel/Process.h b/Kernel/Process.h index d01d87e084..0fb4d2a73f 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -225,6 +225,7 @@ public: int sys$reboot(); int sys$set_process_icon(int icon_id); int sys$realpath(const char* pathname, char*, size_t); + ssize_t sys$getrandom(void*, size_t, unsigned int); static void initialize(); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index ba2880b48a..36eec19782 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -313,6 +313,8 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3 return current->process().sys$get_process_name((char*)arg1, (int)arg2); case Syscall::SC_realpath: return current->process().sys$realpath((const char*)arg1, (char*)arg2, (size_t)arg3); + case Syscall::SC_getrandom: + return current->process().sys$getrandom((void*)arg1, (size_t)arg2, (unsigned int)arg3); default: kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3); return -ENOSYS; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index c8211f11eb..860d7e7e88 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -130,7 +130,8 @@ struct timeval; __ENUMERATE_SYSCALL(mprotect) \ __ENUMERATE_SYSCALL(realpath) \ __ENUMERATE_SYSCALL(get_process_name) \ - __ENUMERATE_SYSCALL(fchdir) + __ENUMERATE_SYSCALL(fchdir) \ + __ENUMERATE_SYSCALL(getrandom) namespace Syscall {