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 {