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

Add devices+config to make random/urandom behave like BSD #1

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 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 drivers/char/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ menu "Character devices"

source "drivers/tty/Kconfig"

config BSD_RANDOM
bool "random and urandom behave like they do on BSDs"
default n
help
When "y", the character devices for /dev/random and /dev/urandom behave
as they do on BSDs. This means that /dev/urandom will block if it hasn't
been initialized yet, and /dev/random will behave identically to
/dev/urandom. When "n" (the default), the legacy kernel behavior is used.

config DEVMEM
bool "/dev/mem virtual device support"
default y
Expand Down
6 changes: 6 additions & 0 deletions drivers/char/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -797,8 +797,14 @@ static const struct memdev {
#endif
[5] = { "zero", 0666, &zero_fops, 0 },
[7] = { "full", 0666, &full_fops, 0 },
#if CONFIG_BSD_RANDOM
[8] = { "random", 0666, &random_fops, 0 },
[9] = { "urandom", 0666, &urandom_fops, 0 },
#else
[8] = { "bsd_urandom", 0666, &bsd_urandom_fops, 0 },
[9] = { "bsd_urandom", 0666, &bsd_urandom_fops, 0 },
#endif
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem quite right - I think you want

#if CONFIG_BSD_RANDOM
     [8] = { "random", 0666, &bsd_urandom_fops, 0 },
     [9] = { "urandom", 0666, &bsd_urandom_fops, 0 },
#else
     [8] = { "random", 0666, &random_fops, 0 },
     [9] = { "urandom", 0666, &urandom_fops, 0 },
#endif
     [13] = { "bsd_urandom", 0666, &bsd_urandom_fops, 0 }

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you think the names are significant, and not just "decorative", or they are decorative but changing them is ~backwards incompatible.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latter. The Kconfig option is

"When "y", the character devices for /dev/random and /dev/urandom behave as they do on BSDs"

which I think is how the code should behave. (Also I think your code as written would attempt to create two bsd_urandoms? Maybe I'm misunderstanding this line of code.)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, this file doesn't create the actual /dev/urandom and /dev/random, it just internally registers the internal things so when you mknod 1 8 /dev/random and mknod 1 9 /dev/urandom it knows where to find the file_operations corresponding to them. Will change the the names to still be random/urandom though.

[13] = { "bsd_urandom", 0666, &bsd_urandom_fops, 0 },
#ifdef CONFIG_PRINTK
[11] = { "kmsg", 0644, &kmsg_fops, 0 },
#endif
Expand Down
36 changes: 36 additions & 0 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,21 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
return ret;
}

static ssize_t
bsd_urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
if (unlikely(nonblocking_pool.initialized == 0)) {
if (file->f_flags & O_NONBLOCK) {
return -EAGAIN;
}
wait_event_interruptible(urandom_init_wait, nonblocking_pool.initialized);
if (signal_pending(current)) {
return -ERESTARTSYS;
}
}
return urandom_read(file, buf, nbytes, ppos);
}

static unsigned int
random_poll(struct file *file, poll_table * wait)
{
Expand All @@ -1488,6 +1503,18 @@ random_poll(struct file *file, poll_table * wait)
return mask;
}

static unsigned int
bsd_urandom_poll(struct file *file, poll_table *wait) {
unsigned int mask = 0;

poll_wait(file, &urandom_init_wait, wait);
mask |= POLLIN | POLLRDNORM;
if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits) {
mask |= POLLOUT | POLLWRNORM;
}
return mask;
}

static int
write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
{
Expand Down Expand Up @@ -1599,6 +1626,15 @@ const struct file_operations urandom_fops = {
.llseek = noop_llseek,
};

const struct file_operations bsd_urandom_fops = {
.read = bsd_urandom_read,
.write = random_write,
.unblocked_ioctl = random_ioctl,
.poll = bsd_urandom_poll,
.fasync = random_fasync,
.llseek = noop_llseek,
}

SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
unsigned int, flags)
{
Expand Down
2 changes: 1 addition & 1 deletion include/linux/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extern void get_random_bytes_arch(void *buf, int nbytes);
extern int random_int_secret_init(void);

#ifndef MODULE
extern const struct file_operations random_fops, urandom_fops;
extern const struct file_operations random_fops, urandom_fops, bsd_urandom_fops;
#endif

unsigned int get_random_int(void);
Expand Down