Skip to content
Snippets Groups Projects
Unverified Commit aefde918 authored by Michael Hamann's avatar Michael Hamann Committed by Oliver Smith
Browse files

linux-samsung-n5110: backport getrandom syscall #107

This is a simple backport of the getrandom syscall. It does not
include other changes to the random interface like periodic or
late re-seeding which might be necessary to get good random numbers.
parent 2f125587
No related branches found
No related tags found
No related merge requests found
From 1c1f660bcb0682a80324e5204a08e59ac93b7a88 Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso@mit.edu>
Date: Thu, 17 Jul 2014 04:13:05 -0400
Subject: [PATCH 1/3] BACKPORT: random: introduce getrandom(2) system call
Almost clean cherry pick of c6e9d6f38894798696f23c8084ca7edbf16ee895,
includes change made by merge 0891ad829d2a0501053703df66029e843e3b8365.
The getrandom(2) system call was requested by the LibreSSL Portable
developers. It is analoguous to the getentropy(2) system call in
OpenBSD.
The rationale of this system call is to provide resiliance against
file descriptor exhaustion attacks, where the attacker consumes all
available file descriptors, forcing the use of the fallback code where
/dev/[u]random is not available. Since the fallback code is often not
well-tested, it is better to eliminate this potential failure mode
entirely.
The other feature provided by this new system call is the ability to
request randomness from the /dev/urandom entropy pool, but to block
until at least 128 bits of entropy has been accumulated in the
/dev/urandom entropy pool. Historically, the emphasis in the
/dev/urandom development has been to ensure that urandom pool is
initialized as quickly as possible after system boot, and preferably
before the init scripts start execution.
This is because changing /dev/urandom reads to block represents an
interface change that could potentially break userspace which is not
acceptable. In practice, on most x86 desktop and server systems, in
general the entropy pool can be initialized before it is needed (and
in modern kernels, we will printk a warning message if not). However,
on an embedded system, this may not be the case. And so with this new
interface, we can provide the functionality of blocking until the
urandom pool has been initialized. Any userspace program which uses
this new functionality must take care to assure that if it is used
during the boot process, that it will not cause the init scripts or
other portions of the system startup to hang indefinitely.
SYNOPSIS
#include <linux/random.h>
int getrandom(void *buf, size_t buflen, unsigned int flags);
DESCRIPTION
The system call getrandom() fills the buffer pointed to by buf
with up to buflen random bytes which can be used to seed user
space random number generators (i.e., DRBG's) or for other
cryptographic uses. It should not be used for Monte Carlo
simulations or other programs/algorithms which are doing
probabilistic sampling.
If the GRND_RANDOM flags bit is set, then draw from the
/dev/random pool instead of the /dev/urandom pool. The
/dev/random pool is limited based on the entropy that can be
obtained from environmental noise, so if there is insufficient
entropy, the requested number of bytes may not be returned.
If there is no entropy available at all, getrandom(2) will
either block, or return an error with errno set to EAGAIN if
the GRND_NONBLOCK bit is set in flags.
If the GRND_RANDOM bit is not set, then the /dev/urandom pool
will be used. Unlike using read(2) to fetch data from
/dev/urandom, if the urandom pool has not been sufficiently
initialized, getrandom(2) will block (or return -1 with the
errno set to EAGAIN if the GRND_NONBLOCK bit is set in flags).
The getentropy(2) system call in OpenBSD can be emulated using
the following function:
int getentropy(void *buf, size_t buflen)
{
int ret;
if (buflen > 256)
goto failure;
ret = getrandom(buf, buflen, 0);
if (ret < 0)
return ret;
if (ret == buflen)
return 0;
failure:
errno = EIO;
return -1;
}
RETURN VALUE
On success, the number of bytes that was filled in the buf is
returned. This may not be all the bytes requested by the
caller via buflen if insufficient entropy was present in the
/dev/random pool, or if the system call was interrupted by a
signal.
On error, -1 is returned, and errno is set appropriately.
ERRORS
EINVAL An invalid flag was passed to getrandom(2)
EFAULT buf is outside the accessible address space.
EAGAIN The requested entropy was not available, and
getentropy(2) would have blocked if the
GRND_NONBLOCK flag was not set.
EINTR While blocked waiting for entropy, the call was
interrupted by a signal handler; see the description
of how interrupted read(2) calls on "slow" devices
are handled with and without the SA_RESTART flag
in the signal(7) man page.
NOTES
For small requests (buflen <= 256) getrandom(2) will not
return EINTR when reading from the urandom pool once the
entropy pool has been initialized, and it will return all of
the bytes that have been requested. This is the recommended
way to use getrandom(2), and is designed for compatibility
with OpenBSD's getentropy() system call.
However, if you are using GRND_RANDOM, then getrandom(2) may
block until the entropy accounting determines that sufficient
environmental noise has been gathered such that getrandom(2)
will be operating as a NRBG instead of a DRBG for those people
who are working in the NIST SP 800-90 regime. Since it may
block for a long time, these guarantees do *not* apply. The
user may want to interrupt a hanging process using a signal,
so blocking until all of the requested bytes are returned
would be unfriendly.
For this reason, the user of getrandom(2) MUST always check
the return value, in case it returns some error, or if fewer
bytes than requested was returned. In the case of
!GRND_RANDOM and small request, the latter should never
happen, but the careful userspace code (and all crypto code
should be careful) should check for this anyway!
Finally, unless you are doing long-term key generation (and
perhaps not even then), you probably shouldn't be using
GRND_RANDOM. The cryptographic algorithms used for
/dev/urandom are quite conservative, and so should be
sufficient for all purposes. The disadvantage of GRND_RANDOM
is that it can block, and the increased complexity required to
deal with partially fulfilled getrandom(2) requests.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Zach Brown <zab@zabbo.net>
Bug: http://b/29621447
Change-Id: I189ba74070dd6d918b0fdf83ff30bb74ec0f7556
(cherry picked from commit 4af712e8df998475736f3e2727701bd31e3751a9)
[flex1911]: backport to 3.4
[michitux]: backport to 3.0, remove x86 support
---
drivers/char/random.c | 52 +++++++++++++++++++++++++++++++-----
include/asm-generic/unistd.h | 4 ++-
include/linux/random.h | 9 +++++++
include/linux/syscalls.h | 3 +++
4 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index e7e479c84233..8d09b53c9102 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -255,6 +255,8 @@
#include <linux/fips.h>
#include <linux/ptrace.h>
#include <linux/kmemcheck.h>
+#include <linux/syscalls.h>
+#include <linux/completion.h>
#ifdef CONFIG_GENERIC_HARDIRQS
# include <linux/irq.h>
@@ -397,6 +399,7 @@ static struct poolinfo {
*/
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait);
static struct fasync_struct *fasync;
#if 0
@@ -607,10 +610,14 @@ retry:
if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
goto retry;
- if (!r->initialized && nbits > 0) {
- r->entropy_total += nbits;
- if (r->entropy_total > 128)
- r->initialized = 1;
+ r->entropy_total += nbits;
+ if (!r->initialized && r->entropy_total > 128) {
+ r->initialized = 1;
+ r->entropy_total = 0;
+ if (r == &nonblocking_pool) {
+ wake_up_interruptible(&urandom_init_wait);
+ pr_notice("random: %s pool is initialized\n", r->name);
+ }
}
trace_credit_entropy_bits(r->name, nbits, entropy_count,
@@ -957,6 +964,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
+
trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
@@ -991,13 +999,14 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
{
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
+ int large_request = (nbytes > 256);
trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
while (nbytes) {
- if (need_resched()) {
+ if (large_request && need_resched()) {
if (signal_pending(current)) {
if (ret == 0)
ret = -ERESTARTSYS;
@@ -1130,7 +1139,7 @@ void rand_initialize_disk(struct gendisk *disk)
#endif
static ssize_t
-random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+_random_read(int nonblock, char __user *buf, size_t nbytes)
{
ssize_t n, retval = 0, count = 0;
@@ -1150,7 +1159,7 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
n*8, (nbytes-n)*8);
if (n == 0) {
- if (file->f_flags & O_NONBLOCK) {
+ if (nonblock) {
retval = -EAGAIN;
break;
}
@@ -1185,6 +1194,12 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
return (count ? count : retval);
}
+static ssize_t
+random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+{
+ return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
static ssize_t
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
@@ -1311,6 +1326,29 @@ const struct file_operations urandom_fops = {
.llseek = noop_llseek,
};
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+ unsigned int, flags)
+{
+ if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
+ return -EINVAL;
+
+ if (count > INT_MAX)
+ count = INT_MAX;
+
+ if (flags & GRND_RANDOM)
+ return _random_read(flags & GRND_NONBLOCK, buf, count);
+
+ if (unlikely(nonblocking_pool.initialized == 0)) {
+ if (flags & GRND_NONBLOCK)
+ return -EAGAIN;
+ wait_event_interruptible(urandom_init_wait,
+ nonblocking_pool.initialized);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+ return urandom_read(NULL, buf, count, NULL);
+}
+
/***************************************************************
* Random UUID interface
*
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index 5518963e38b0..4eeff0f900ac 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -685,9 +685,11 @@ __SYSCALL(__NR_syncfs, sys_syncfs)
__SYSCALL(__NR_setns, sys_setns)
#define __NR_sendmmsg 269
__SC_COMP(__NR_sendmmsg, sys_sendmmsg, compat_sys_sendmmsg)
+#define __NR_getrandom 278
+__SYSCALL(__NR_getrandom, sys_getrandom)
#undef __NR_syscalls
-#define __NR_syscalls 270
+#define __NR_syscalls 279
/*
* All syscalls below here should go away really,
diff --git a/include/linux/random.h b/include/linux/random.h
index 7e58ad27b7ff..788834fb7969 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -46,6 +46,15 @@ struct rnd_state {
/* Exported functions */
+/*
+ * Flags for getrandom(2)
+ *
+ * GRND_NONBLOCK Don't block and return EAGAIN instead
+ * GRND_RANDOM Use the /dev/random pool instead of /dev/urandom
+ */
+#define GRND_NONBLOCK 0x0001
+#define GRND_RANDOM 0x0002
+
#ifdef __KERNEL__
extern void add_device_randomness(const void *, unsigned int);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 8c03b98df5f9..6935b215e34c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -847,4 +847,7 @@ asmlinkage long sys_open_by_handle_at(int mountdirfd,
struct file_handle __user *handle,
int flags);
asmlinkage long sys_setns(int fd, int nstype);
+asmlinkage long sys_getrandom(char __user *buf, size_t count,
+ unsigned int flags);
+
#endif
--
2.19.0
From ad7154f084e30ed053a616fd1ebe1d969c2b742a Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Thu, 21 May 2015 16:19:54 +0800
Subject: [PATCH 2/3] BACKPORT: random: Wake up all getrandom(2) callers when
pool is ready
Clean cherry pick of 1d9de44e268d880cbe2d0bd3be1ef0661f93fd34.
If more than one application invokes getrandom(2) before the pool
is ready, then all bar one will be stuck forever because we use
wake_up_interruptible which wakes up a single task.
This patch replaces it with wake_up_all.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Bug: http://b/29621447
Change-Id: I5dfd7abac10898802f030e0a2af7110809283328
(cherry picked from commit 1d9de44e268d880cbe2d0bd3be1ef0661f93fd34)
---
drivers/char/random.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 8d09b53c9102..702b5bcad2c8 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -615,7 +615,7 @@ retry:
r->initialized = 1;
r->entropy_total = 0;
if (r == &nonblocking_pool) {
- wake_up_interruptible(&urandom_init_wait);
+ wake_up_all(&urandom_init_wait);
pr_notice("random: %s pool is initialized\n", r->name);
}
}
--
2.19.0
From d919f1f5c38205ad2ab38d4c061e8b28e606559b Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@arm.linux.org.uk>
Date: Fri, 8 Aug 2014 10:56:34 +0100
Subject: [PATCH 3/3] BACKPORT: ARM: wire up getrandom syscall
Clean cherry pick of eb6452537b280652eee66801ec97cc369e27e5d8.
Add the new getrandom syscall for ARM.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Bug: http://b/29621447
Change-Id: I6d50b57f3a61fbf9102c69103b9a5b7ebf239860
(cherry picked from commit eb6452537b280652eee66801ec97cc369e27e5d8)
[flex1911]: backport to 3.4
[michitux]: backport to 3.0
---
arch/arm/include/asm/unistd.h | 9 +++++++++
arch/arm/kernel/calls.S | 9 +++++++++
2 files changed, 18 insertions(+)
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 2c04ed5efeb5..96e290b9fecf 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -402,6 +402,7 @@
#define __NR_syncfs (__NR_SYSCALL_BASE+373)
#define __NR_sendmmsg (__NR_SYSCALL_BASE+374)
#define __NR_setns (__NR_SYSCALL_BASE+375)
+#define __NR_getrandom (__NR_SYSCALL_BASE+384)
/*
* The following SWIs are ARM private.
@@ -413,6 +414,14 @@
#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
+/*
+ * This may need to be greater than __NR_last_syscall+1 in order to
+ * account for the padding in the syscall table
+ */
+#ifdef __KERNEL__
+#define __NR_syscalls (388)
+#endif
+
/*
* *NOTE*: This is a ghost syscall private to the kernel. Only the
* __kuser_cmpxchg code in entry-armv.S should be aware of its
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 80f7896cc016..612627f899d4 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -385,6 +385,15 @@
CALL(sys_syncfs)
CALL(sys_sendmmsg)
/* 375 */ CALL(sys_setns)
+ CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall)
+/* 380 */ CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall)
+ CALL(sys_getrandom)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
--
2.19.0
......@@ -2,7 +2,7 @@
pkgname="linux-samsung-n5110"
pkgver=3.0.101
pkgrel=1
pkgrel=2
pkgdesc="Samsung Galaxy Note 8.0 (Wi-Fi) kernel fork"
arch="armhf"
_carch="arm"
......@@ -28,6 +28,9 @@ _config="config-${_flavor}.${arch}"
source="
$pkgname-$_commit.tar.gz::https://github.com/LineageOS/${_repository}/archive/${_commit}.tar.gz
$_config
0001-BACKPORT-random-introduce-getrandom-2-system-call.patch
0002-BACKPORT-random-Wake-up-all-getrandom-2-callers-when.patch
0003-BACKPORT-ARM-wire-up-getrandom-syscall.patch
compiler-gcc6.h
"
builddir="$srcdir/${_repository}-${_commit}"
......@@ -77,4 +80,7 @@ package() {
sha512sums="7e47ecfa6c3b2f4ac199ceed4103a00a577f9fa0002f5759df570f3c11a3436e53114e87a13e9efd27f2a2e17fcaab1be0666dffaa7d23699e700bee0d2afe33 linux-samsung-n5110-b7ffe7f2aea2391737cdeac2a33217ee0ea4f2ba.tar.gz
0d0219494704891d06c85929ed2d73db49c581874ad04c9e11f625dd06a499854a1ec813dd7073fb9bb88a91f17510ae168e38716986de324e156e45d6fb965e config-samsung-n5110.armhf
9f931974afda5f82dab400758aa35decb97678ef698748c56dae4b2ede62fab34c3a7d6c16293602cfbb7a6a41d64ac3d25b8cb63251bef23475d50bfaae16a6 0001-BACKPORT-random-introduce-getrandom-2-system-call.patch
5d64e22eaeddc4a7fd4b99076bd2e29c02c214852663d6ddb30d304e9aba1f177f8c25e15f7892045cc132ef80e148952128536817fa8af6f03f3c7ee33d33a3 0002-BACKPORT-random-Wake-up-all-getrandom-2-callers-when.patch
8ce10fba0b10131de07a9c47544702b68c52f2e0a09eb2942044abf2e292cbfacbac0b6f6445306af46915064573037cfd66f99500bfa75551daa9376b1a6f77 0003-BACKPORT-ARM-wire-up-getrandom-syscall.patch
d80980e9474c82ba0ef1a6903b434d8bd1b092c40367ba543e72d2c119301c8b2d05265740e4104ca1ac5d15f6c4aa49e8776cb44264a9a28dc551e0d1850dcc compiler-gcc6.h"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment