Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport getrandom syscall #11

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions arch/arm/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@
#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376)
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
#define __NR_seccomp (__NR_SYSCALL_BASE+383)
#define __NR_getrandom (__NR_SYSCALL_BASE+384)

/*
* The following SWIs are ARM private.
Expand All @@ -416,6 +417,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
Expand Down
1 change: 1 addition & 0 deletions arch/arm/kernel/calls.S
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@
CALL(sys_ni_syscall)
CALL(sys_ni_syscall)
CALL(sys_seccomp)
CALL(sys_getrandom)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
Expand Down
1 change: 1 addition & 0 deletions arch/x86/syscalls/syscall_32.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -356,3 +356,4 @@
347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
354 i386 seccomp sys_seccomp
355 i386 getrandom sys_getrandom
1 change: 1 addition & 0 deletions arch/x86/syscalls/syscall_64.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@
310 64 process_vm_readv sys_process_vm_readv
311 64 process_vm_writev sys_process_vm_writev
317 common seccomp sys_seccomp
318 common getrandom sys_getrandom

#
# x32-specific system call numbers start at 512 to avoid cache impact
Expand Down
52 changes: 45 additions & 7 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -607,10 +610,15 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
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) {
prandom_reseed_late();
wake_up_all(&urandom_init_wait);
pr_notice("random: %s pool is initialized\n", r->name);
}
}

trace_credit_entropy_bits(r->name, nbits, entropy_count,
Expand Down Expand Up @@ -999,13 +1007,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;
Expand Down Expand Up @@ -1138,7 +1147,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;

Expand All @@ -1158,7 +1167,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;
}
Expand Down Expand Up @@ -1193,6 +1202,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)
{
Expand Down Expand Up @@ -1319,6 +1334,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
*
Expand Down
4 changes: 2 additions & 2 deletions drivers/scsi/fcoe/fcoe_ctlr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2048,7 +2048,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
*/
port_id = fip->port_id;
if (fip->probe_tries)
port_id = prandom32(&fip->rnd_state) & 0xffff;
port_id = prandom_u32_state(&fip->rnd_state) & 0xffff;
else if (!port_id)
port_id = fip->lp->wwpn & 0xffff;
if (!port_id || port_id == 0xffff)
Expand All @@ -2073,7 +2073,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
{
fip->probe_tries = 0;
prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
prandom_seed_state(&fip->rnd_state, fip->lp->wwpn);
fcoe_ctlr_vn_restart(fip);
}

Expand Down
4 changes: 3 additions & 1 deletion include/asm-generic/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,9 +693,11 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
compat_sys_process_vm_writev)
#define __NR_seccomp 277
__SYSCALL(__NR_seccomp, sys_seccomp)
#define __NR_getrandom 278
__SYSCALL(__NR_getrandom, sys_getrandom)

#undef __NR_syscalls
#define __NR_syscalls 278
#define __NR_syscalls 279

/*
* All syscalls below here should go away really,
Expand Down
29 changes: 24 additions & 5 deletions include/linux/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -66,10 +75,20 @@ unsigned int get_random_int(void);
unsigned long get_random_long(void);
unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);

u32 random32(void);
void srandom32(u32 seed);
u32 prandom_u32(void);
void prandom_bytes(void *buf, int nbytes);
void prandom_seed(u32 seed);
void prandom_reseed_late(void);

/*
* These macros are preserved for backward compatibility and should be
* removed as soon as a transition is finished.
*/
#define random32() prandom_u32()
#define srandom32(seed) prandom_seed(seed)

u32 prandom32(struct rnd_state *);
u32 prandom_u32_state(struct rnd_state *);
void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes);

/*
* Handle minimum values for seeds
Expand All @@ -80,11 +99,11 @@ static inline u32 __seed(u32 x, u32 m)
}

/**
* prandom32_seed - set seed for prandom32().
* prandom_seed_state - set seed for prandom_u32_state().
* @state: pointer to state structure to receive the seed.
* @seed: arbitrary 64-bit value to use as a seed.
*/
static inline void prandom32_seed(struct rnd_state *state, u64 seed)
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
{
u32 i = (seed >> 32) ^ (seed << 10) ^ seed;

Expand Down
2 changes: 2 additions & 0 deletions include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,4 +860,6 @@ asmlinkage long sys_process_vm_writev(pid_t pid,

asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
const char __user *uargs);
asmlinkage long sys_getrandom(char __user *buf, size_t count,
unsigned int flags);
#endif
Loading