Skip to content

Commit 57a74cc

Browse files
Tofeeshr-project
authored andcommitted
Backport getrandom syscall
Signed-off-by: Christophe Chapuis <[email protected]>
1 parent 9ef22c8 commit 57a74cc

File tree

10 files changed

+206
-39
lines changed

10 files changed

+206
-39
lines changed

arch/arm/include/asm/unistd.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@
405405
#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376)
406406
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
407407
#define __NR_seccomp (__NR_SYSCALL_BASE+383)
408+
#define __NR_getrandom (__NR_SYSCALL_BASE+384)
408409

409410
/*
410411
* The following SWIs are ARM private.
@@ -416,6 +417,14 @@
416417
#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
417418
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
418419

420+
/*
421+
* This may need to be greater than __NR_last_syscall+1 in order to
422+
* account for the padding in the syscall table
423+
*/
424+
#ifdef __KERNEL__
425+
#define __NR_syscalls (388)
426+
#endif
427+
419428
/*
420429
* *NOTE*: This is a ghost syscall private to the kernel. Only the
421430
* __kuser_cmpxchg code in entry-armv.S should be aware of its

arch/arm/kernel/calls.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@
393393
CALL(sys_ni_syscall)
394394
CALL(sys_ni_syscall)
395395
CALL(sys_seccomp)
396+
CALL(sys_getrandom)
396397
#ifndef syscalls_counted
397398
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
398399
#define syscalls_counted

arch/x86/syscalls/syscall_32.tbl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,4 @@
356356
347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
357357
348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
358358
354 i386 seccomp sys_seccomp
359+
355 i386 getrandom sys_getrandom

arch/x86/syscalls/syscall_64.tbl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@
319319
310 64 process_vm_readv sys_process_vm_readv
320320
311 64 process_vm_writev sys_process_vm_writev
321321
317 common seccomp sys_seccomp
322+
318 common getrandom sys_getrandom
322323

323324
#
324325
# x32-specific system call numbers start at 512 to avoid cache impact

drivers/char/random.c

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@
255255
#include <linux/fips.h>
256256
#include <linux/ptrace.h>
257257
#include <linux/kmemcheck.h>
258+
#include <linux/syscalls.h>
259+
#include <linux/completion.h>
258260

259261
#ifdef CONFIG_GENERIC_HARDIRQS
260262
# include <linux/irq.h>
@@ -397,6 +399,7 @@ static struct poolinfo {
397399
*/
398400
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
399401
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
402+
static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait);
400403
static struct fasync_struct *fasync;
401404

402405
#if 0
@@ -607,10 +610,15 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
607610
if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
608611
goto retry;
609612

610-
if (!r->initialized && nbits > 0) {
611-
r->entropy_total += nbits;
612-
if (r->entropy_total > 128)
613-
r->initialized = 1;
613+
r->entropy_total += nbits;
614+
if (!r->initialized && r->entropy_total > 128) {
615+
r->initialized = 1;
616+
r->entropy_total = 0;
617+
if (r == &nonblocking_pool) {
618+
prandom_reseed_late();
619+
wake_up_all(&urandom_init_wait);
620+
pr_notice("random: %s pool is initialized\n", r->name);
621+
}
614622
}
615623

616624
trace_credit_entropy_bits(r->name, nbits, entropy_count,
@@ -999,13 +1007,14 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
9991007
{
10001008
ssize_t ret = 0, i;
10011009
__u8 tmp[EXTRACT_SIZE];
1010+
int large_request = (nbytes > 256);
10021011

10031012
trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
10041013
xfer_secondary_pool(r, nbytes);
10051014
nbytes = account(r, nbytes, 0, 0);
10061015

10071016
while (nbytes) {
1008-
if (need_resched()) {
1017+
if (large_request && need_resched()) {
10091018
if (signal_pending(current)) {
10101019
if (ret == 0)
10111020
ret = -ERESTARTSYS;
@@ -1138,7 +1147,7 @@ void rand_initialize_disk(struct gendisk *disk)
11381147
#endif
11391148

11401149
static ssize_t
1141-
random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1150+
_random_read(int nonblock, char __user *buf, size_t nbytes)
11421151
{
11431152
ssize_t n, retval = 0, count = 0;
11441153

@@ -1158,7 +1167,7 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
11581167
n*8, (nbytes-n)*8);
11591168

11601169
if (n == 0) {
1161-
if (file->f_flags & O_NONBLOCK) {
1170+
if (nonblock) {
11621171
retval = -EAGAIN;
11631172
break;
11641173
}
@@ -1193,6 +1202,12 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
11931202
return (count ? count : retval);
11941203
}
11951204

1205+
static ssize_t
1206+
random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1207+
{
1208+
return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
1209+
}
1210+
11961211
static ssize_t
11971212
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
11981213
{
@@ -1319,6 +1334,29 @@ const struct file_operations urandom_fops = {
13191334
.llseek = noop_llseek,
13201335
};
13211336

1337+
SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
1338+
unsigned int, flags)
1339+
{
1340+
if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
1341+
return -EINVAL;
1342+
1343+
if (count > INT_MAX)
1344+
count = INT_MAX;
1345+
1346+
if (flags & GRND_RANDOM)
1347+
return _random_read(flags & GRND_NONBLOCK, buf, count);
1348+
1349+
if (unlikely(nonblocking_pool.initialized == 0)) {
1350+
if (flags & GRND_NONBLOCK)
1351+
return -EAGAIN;
1352+
wait_event_interruptible(urandom_init_wait,
1353+
nonblocking_pool.initialized);
1354+
if (signal_pending(current))
1355+
return -ERESTARTSYS;
1356+
}
1357+
return urandom_read(NULL, buf, count, NULL);
1358+
}
1359+
13221360
/***************************************************************
13231361
* Random UUID interface
13241362
*

drivers/scsi/fcoe/fcoe_ctlr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,7 +2048,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
20482048
*/
20492049
port_id = fip->port_id;
20502050
if (fip->probe_tries)
2051-
port_id = prandom32(&fip->rnd_state) & 0xffff;
2051+
port_id = prandom_u32_state(&fip->rnd_state) & 0xffff;
20522052
else if (!port_id)
20532053
port_id = fip->lp->wwpn & 0xffff;
20542054
if (!port_id || port_id == 0xffff)
@@ -2073,7 +2073,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
20732073
static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
20742074
{
20752075
fip->probe_tries = 0;
2076-
prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
2076+
prandom_seed_state(&fip->rnd_state, fip->lp->wwpn);
20772077
fcoe_ctlr_vn_restart(fip);
20782078
}
20792079

include/asm-generic/unistd.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,9 +693,11 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
693693
compat_sys_process_vm_writev)
694694
#define __NR_seccomp 277
695695
__SYSCALL(__NR_seccomp, sys_seccomp)
696+
#define __NR_getrandom 278
697+
__SYSCALL(__NR_getrandom, sys_getrandom)
696698

697699
#undef __NR_syscalls
698-
#define __NR_syscalls 278
700+
#define __NR_syscalls 279
699701

700702
/*
701703
* All syscalls below here should go away really,

include/linux/random.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ struct rnd_state {
4646

4747
/* Exported functions */
4848

49+
/*
50+
* Flags for getrandom(2)
51+
*
52+
* GRND_NONBLOCK Don't block and return EAGAIN instead
53+
* GRND_RANDOM Use the /dev/random pool instead of /dev/urandom
54+
*/
55+
#define GRND_NONBLOCK 0x0001
56+
#define GRND_RANDOM 0x0002
57+
4958
#ifdef __KERNEL__
5059

5160
extern void add_device_randomness(const void *, unsigned int);
@@ -66,10 +75,20 @@ unsigned int get_random_int(void);
6675
unsigned long get_random_long(void);
6776
unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
6877

69-
u32 random32(void);
70-
void srandom32(u32 seed);
78+
u32 prandom_u32(void);
79+
void prandom_bytes(void *buf, int nbytes);
80+
void prandom_seed(u32 seed);
81+
void prandom_reseed_late(void);
82+
83+
/*
84+
* These macros are preserved for backward compatibility and should be
85+
* removed as soon as a transition is finished.
86+
*/
87+
#define random32() prandom_u32()
88+
#define srandom32(seed) prandom_seed(seed)
7189

72-
u32 prandom32(struct rnd_state *);
90+
u32 prandom_u32_state(struct rnd_state *);
91+
void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes);
7392

7493
/*
7594
* Handle minimum values for seeds
@@ -80,11 +99,11 @@ static inline u32 __seed(u32 x, u32 m)
8099
}
81100

82101
/**
83-
* prandom32_seed - set seed for prandom32().
102+
* prandom_seed_state - set seed for prandom_u32_state().
84103
* @state: pointer to state structure to receive the seed.
85104
* @seed: arbitrary 64-bit value to use as a seed.
86105
*/
87-
static inline void prandom32_seed(struct rnd_state *state, u64 seed)
106+
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
88107
{
89108
u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
90109

include/linux/syscalls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,4 +860,6 @@ asmlinkage long sys_process_vm_writev(pid_t pid,
860860

861861
asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
862862
const char __user *uargs);
863+
asmlinkage long sys_getrandom(char __user *buf, size_t count,
864+
unsigned int flags);
863865
#endif

0 commit comments

Comments
 (0)