Browse Source

add getentropy(), fix return value of getrandom()

Signed-off-by: Thorsten Glaser <tg@debian.org>
Thorsten Glaser 4 weeks ago
parent
commit
8a6bb3fb10

+ 9 - 0
include/unistd.h

@@ -1250,6 +1250,15 @@ extern void swab (const void *__restrict __from, void *__restrict __to,
 extern char *ctermid (char *__s) __THROW;
 #endif
 
+/* OpenBSD-compatible access to random bytes.
+   May be a cancellation point here, unlike in glibc/musl.  */
+#ifdef _DEFAULT_SOURCE
+# ifndef __getentropy_defined
+extern int getentropy(void *__buf, size_t __len) __nonnull ((1)) __wur;
+#  define __getentropy_defined
+# endif
+#endif
+
 __END_DECLS
 
 

+ 43 - 0
libc/sysdeps/linux/common/getentropy.c

@@ -0,0 +1,43 @@
+/*
+ * getentropy() by wrapping getrandom(), for µClibc-ng
+ *
+ * © 2025 mirabilos Ⓕ CC0 or MirBSD or GNU LGPLv2
+ *
+ * Note: may be a thread cancellation point, unlike the
+ * implementations in glibc and musl libc. Should this
+ * ever become a concern, it will need patching.
+ */
+
+#define _DEFAULT_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <sys/random.h>
+
+int
+getentropy(void *__buf, size_t __len)
+{
+	ssize_t n;
+
+	if (__len > 256U) {
+		errno = EIO;
+		return (-1);
+	}
+
+ again:
+	if ((n = getrandom(__buf, __len, 0)) == -1)
+		switch (errno) {
+		case EAGAIN: /* should not happen but better safe than sorry */
+		case EINTR:
+			goto again;
+		default:
+			errno = EIO;
+			/* FALLTHROUGH */
+		case EFAULT:
+		case ENOSYS:
+			return (-1);
+		}
+	if ((size_t)n != __len)
+		/* also shouldn’t happen (safety net) */
+		goto again;
+	return (0);
+}

+ 2 - 1
libc/sysdeps/linux/common/getrandom.c

@@ -8,6 +8,7 @@
 
 #include <sys/syscall.h>
 #include <sys/random.h>
+
 #ifdef __NR_getrandom
-_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
+_syscall3(ssize_t, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
 #endif

+ 16 - 2
libc/sysdeps/linux/common/sys/random.h

@@ -4,11 +4,19 @@
 
 #ifndef	_SYS_RANDOM_H
 #define	_SYS_RANDOM_H	1
+
 #include <features.h>
 #include <stddef.h>
 
 __BEGIN_DECLS
 
+#include <bits/types.h>
+
+#ifndef __ssize_t_defined
+typedef __ssize_t ssize_t;
+# define __ssize_t_defined
+#endif
+
 #if defined __UCLIBC_LINUX_SPECIFIC__
 # if 0 /*def __ASSUME_GETRANDOM_SYSCALL */
 #  include <linux/random.h>
@@ -26,9 +34,15 @@ __BEGIN_DECLS
 #  define GRND_RANDOM	0x0002
 #  define GRND_INSECURE 0x0004
 # endif
-/* FIXME: aren't there a couple of __restrict and const missing ? */
-extern int getrandom(void *__buf, size_t count, unsigned int flags)
+extern ssize_t getrandom(void *__buf, size_t count, unsigned int flags)
 	   __nonnull ((1)) __wur;
+
+/* OpenBSD-compatible access to random bytes.
+   May be a cancellation point here, unlike in glibc/musl.  */
+# ifndef __getentropy_defined
+extern int getentropy(void *__buf, size_t __len) __nonnull ((1)) __wur;
+#  define __getentropy_defined
+# endif
 #endif
 
 __END_DECLS