Author: archaic Date: 2005-03-05 07:39:10 -0700 (Sat, 05 Mar 2005) New Revision: 856
Added: trunk/hlfs/linux-2.6.11-pseudo_random-1.patch trunk/linux/linux-2.6.11-pseudo_random-1.patch Removed: trunk/hlfs/linux-2.6.10-pseudo_random-1.patch trunk/linux/linux-2.6.10-pseudo_random-1.patch Log: Update kernel frandom patch to 2.6.11 Deleted: trunk/hlfs/linux-2.6.10-pseudo_random-1.patch =================================================================== --- trunk/hlfs/linux-2.6.10-pseudo_random-1.patch 2005-03-05 14:36:41 UTC (rev 855) +++ trunk/hlfs/linux-2.6.10-pseudo_random-1.patch 2005-03-05 14:39:10 UTC (rev 856) @@ -1,617 +0,0 @@ -Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes) -Date: 2005-02-12 -Initial Package Version: 2.6.10 -Upstream Status: Not submitted -Origin: http://frandom.sourceforge.net/ -Description: This patch adds the he frandom, and erandom devices, and a -sysctl interface for urandom. Udev's permissions need modifications to add -/dev/frandom and /dev/erandom. - -Also see: -http://www.linuxfromscratch.org/hlfs/ -http://www.linuxfromscratch.org/hints/downloads/files/entropy.txt - -diff -Naur linux-2.6.10.orig/drivers/char/Kconfig linux-2.6.10/drivers/char/Kconfig ---- linux-2.6.10.orig/drivers/char/Kconfig 2004-12-24 21:33:49.000000000 +0000 -+++ linux-2.6.10/drivers/char/Kconfig 2005-02-11 13:08:21.327917144 +0000 -@@ -57,6 +57,19 @@ - - If unsure, say Y. - -+config FRANDOM -+ tristate "Fast random data generator suite (/dev/frandom and /dev/erandom)" -+ default y -+ ---help--- -+ Fast random data/number generator support in kernel. This random -+ generator is 10-50 times faster than /dev/urandom, and saves kernel -+ entropy. -+ -+ If unsure, say Y unless you're tight on kernel size. This module is -+ small and harmless otherwise. -+ -+ If you choose M, the sysctl interface will be disabled. -+ - config HW_CONSOLE - bool - depends on VT && !S390 && !USERMODE -diff -Naur linux-2.6.10.orig/drivers/char/Makefile linux-2.6.10/drivers/char/Makefile ---- linux-2.6.10.orig/drivers/char/Makefile 2004-12-24 21:35:29.000000000 +0000 -+++ linux-2.6.10/drivers/char/Makefile 2005-02-11 13:09:19.614056304 +0000 -@@ -9,6 +9,8 @@ - - obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o - -+obj-$(CONFIG_FRANDOM) += frandom.o -+ - obj-$(CONFIG_LEGACY_PTYS) += pty.o - obj-$(CONFIG_UNIX98_PTYS) += pty.o - obj-y += misc.o -diff -Naur linux-2.6.10.orig/drivers/char/frandom.c linux-2.6.10/drivers/char/frandom.c ---- linux-2.6.10.orig/drivers/char/frandom.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.10/drivers/char/frandom.c 2005-02-10 07:00:11.608466208 +0000 -@@ -0,0 +1,387 @@ -+/* -+** frandom.c -+** Fast pseudo-random generator -+** -+** (c) Copyright 2003 Eli Billauer -+** http://www.billauer.co.il -+** -+** This program is free software; you can redistribute it and/or modify -+** it under the terms of the GNU General Public License as published by -+** the Free Software Foundation; either version 2 of the License, or -+** (at your option) any later version. -+** -+** Usage: mknod /dev/frandom c 235 11 -+** mknod /dev/erandom c 235 12 -+** insmod frandom -+** -+** This code is highly based upon the examples given in the book "Linux -+** Device Drivers" by Alessandro Rubini and Jonathan Corbet, published -+** by O'Reilly & Associates. -+** O'Reilly's release of this book on the web for free is highly -+** appreciated. -+** -+*/ -+ -+#include <linux/version.h> -+#include <linux/config.h> -+#include <linux/module.h> -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/fs.h> -+#include <linux/errno.h> -+#include <linux/types.h> -+#include <linux/random.h> -+ -+#include <linux/devfs_fs_kernel.h> -+#include <linux/device.h> -+ -+#include <asm/uaccess.h> -+ -+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,0)) -+#include <linux/moduleparam.h> -+#endif -+ -+#define INTERNAL_SEED 0 -+#define EXTERNAL_SEED 1 -+ -+#define FRANDOM_MAJOR 235 -+#define FRANDOM_MINOR 11 -+#define ERANDOM_MINOR 12 -+ -+static struct file_operations frandom_fops; /* Values assigned below */ -+ -+static int erandom_seeded = 0; /* Internal flag */ -+ -+static int frandom_major = FRANDOM_MAJOR; -+static int frandom_minor = FRANDOM_MINOR; -+static int erandom_minor = ERANDOM_MINOR; -+static int frandom_bufsize = 256; -+static int frandom_chunklimit = 0; /* =0 means unlimited */ -+ -+MODULE_DESCRIPTION("Fast pseudo-random number generator"); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Eli Billauer"); -+MODULE_PARM(frandom_major,"i"); -+MODULE_PARM_DESC(frandom_major,"Major number of /dev/frandom and /dev/erandom"); -+MODULE_PARM(frandom_minor,"i"); -+MODULE_PARM_DESC(frandom_minor,"Minor number of /dev/frandom"); -+MODULE_PARM(erandom_minor,"i"); -+MODULE_PARM_DESC(erandom_minor,"Minor number of /dev/erandom"); -+MODULE_PARM(frandom_bufsize,"i"); -+MODULE_PARM_DESC(frandom_bufsize,"Internal buffer size in bytes. Default is 256. Must be >= 256"); -+MODULE_PARM(frandom_chunklimit,"i"); -+MODULE_PARM_DESC(frandom_chunklimit,"Limit for read() blocks size. 0 (default) is unlimited, otherwise must be >= 256"); -+ -+struct frandom_state -+{ -+ struct semaphore sem; /* Semaphore on the state structure */ -+ -+ u8 S[256]; /* The state array */ -+ u8 i; -+ u8 j; -+ -+ char *buf; -+}; -+ -+static struct frandom_state *erandom_state; -+ -+static inline void swap_byte(u8 *a, u8 *b) -+{ -+ u8 swapByte; -+ -+ swapByte = *a; -+ *a = *b; -+ *b = swapByte; -+} -+ -+static void init_rand_state(struct frandom_state *state, int seedflag); -+ -+void erandom_get_random_bytes(char *buf, size_t count) -+{ -+ struct frandom_state *state = erandom_state; -+ int k; -+ -+ unsigned int i; -+ unsigned int j; -+ u8 *S; -+ -+ /* If we fail to get the semaphore, we revert to external random data. -+ Since semaphore blocking is expected to be very rare, and interrupts -+ during these rare and very short periods of time even less frequent, -+ we take the better-safe-than-sorry approach, and fill the buffer -+ some expensive random data, in case the caller wasn't aware of this -+ possibility, and expects random data anyhow. -+ */ -+ -+ if (down_interruptible(&state->sem)) { -+ get_random_bytes(buf, count); -+ return; -+ } -+ -+ /* We seed erandom as late as possible, hoping that the kernel's main -+ RNG is already restored in the boot sequence (not critical, but -+ better. -+ */ -+ -+ if (!erandom_seeded) { -+ erandom_seeded = 1; -+ init_rand_state(state, EXTERNAL_SEED); -+ printk(KERN_INFO "frandom: Seeded global generator now (used by erandom)\n"); -+ } -+ -+ i = state->i; -+ j = state->j; -+ S = state->S; -+ -+ for (k=0; k<count; k++) { -+ i = (i + 1) & 0xff; -+ j = (j + S[i]) & 0xff; -+ swap_byte(&S[i], &S[j]); -+ *buf++ = S[(S[i] + S[j]) & 0xff]; -+ } -+ -+ state->i = i; -+ state->j = j; -+ -+ up(&state->sem); -+} -+ -+static void init_rand_state(struct frandom_state *state, int seedflag) -+{ -+ unsigned int i, j, k; -+ u8 *S; -+ u8 *seed = state->buf; -+ -+ if (seedflag == INTERNAL_SEED) -+ erandom_get_random_bytes(seed, 256); -+ else -+ get_random_bytes(seed, 256); -+ -+ S = state->S; -+ for (i=0; i<256; i++) -+ *S++=i; -+ -+ j=0; -+ S = state->S; -+ -+ for (i=0; i<256; i++) { -+ j = (j + S[i] + *seed++) & 0xff; -+ swap_byte(&S[i], &S[j]); -+ } -+ -+ /* It's considered good practice to discard the first 256 bytes -+ generated. So we do it: -+ */ -+ -+ i=0; j=0; -+ for (k=0; k<256; k++) { -+ i = (i + 1) & 0xff; -+ j = (j + S[i]) & 0xff; -+ swap_byte(&S[i], &S[j]); -+ } -+ -+ state->i = i; /* Save state */ -+ state->j = j; -+} -+ -+static int frandom_open(struct inode *inode, struct file *filp) -+{ -+ -+ struct frandom_state *state; -+ -+ int num =MINOR(inode->i_rdev); -+ if ((num != frandom_minor) && (num != erandom_minor)) return -ENODEV; -+ -+ state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); -+ if (!state) -+ return -ENOMEM; -+ -+ state->buf = kmalloc(frandom_bufsize, GFP_KERNEL); -+ if (!state->buf) { -+ kfree(state); -+ return -ENOMEM; -+ } -+ -+ sema_init(&state->sem, 1); /* Init semaphore as a mutex */ -+ -+ if (num == frandom_minor) -+ init_rand_state(state, EXTERNAL_SEED); -+ else -+ init_rand_state(state, INTERNAL_SEED); -+ -+ filp->private_data = state; -+ -+#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0)) -+ MOD_INC_USE_COUNT; -+#endif -+ -+ return 0; /* Success */ -+} -+ -+static int frandom_release(struct inode *inode, struct file *filp) -+{ -+ -+ struct frandom_state *state = filp->private_data; -+ -+ kfree(state->buf); -+ kfree(state); -+ -+#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0)) -+ MOD_DEC_USE_COUNT; -+#endif -+ -+ return 0; -+} -+ -+static ssize_t frandom_read(struct file *filp, char *buf, size_t count, -+ loff_t *f_pos) -+{ -+ struct frandom_state *state = filp->private_data; -+ ssize_t ret; -+ int dobytes, k; -+ char *localbuf; -+ -+ unsigned int i; -+ unsigned int j; -+ u8 *S; -+ -+ if (down_interruptible(&state->sem)) -+ return -ERESTARTSYS; -+ -+ if ((frandom_chunklimit > 0) && (count > frandom_chunklimit)) -+ count = frandom_chunklimit; -+ -+ ret = count; /* It's either everything or an error... */ -+ -+ i = state->i; -+ j = state->j; -+ S = state->S; -+ -+ while (count) { -+ if (count > frandom_bufsize) -+ dobytes = frandom_bufsize; -+ else -+ dobytes = count; -+ -+ localbuf = state->buf; -+ -+ for (k=0; k<dobytes; k++) { -+ i = (i + 1) & 0xff; -+ j = (j + S[i]) & 0xff; -+ swap_byte(&S[i], &S[j]); -+ *localbuf++ = S[(S[i] + S[j]) & 0xff]; -+ } -+ -+ if (copy_to_user(buf, state->buf, dobytes)) { -+ ret = -EFAULT; -+ goto out; -+ } -+ -+ buf += dobytes; -+ count -= dobytes; -+ } -+ -+ out: -+ state->i = i; -+ state->j = j; -+ -+ up(&state->sem); -+ return ret; -+} -+ -+static struct file_operations frandom_fops = { -+ read: frandom_read, -+ open: frandom_open, -+ release: frandom_release, -+}; -+ -+static const struct { -+ unsigned int minor; -+ char *name; -+ umode_t mode; -+ struct file_operations *fops; -+} devlist[] = { -+ {11, "frandom", S_IRUGO | S_IWUSR, &frandom_fops}, -+ /* Erandom doesn't have its own fop, it shares one with frandom. */ -+ {12, "erandom", S_IRUGO | S_IWUSR, &frandom_fops}, -+}; -+ -+static struct class_simple *frandom_class; -+ -+static void frandom_cleanup_module(void) { -+ kfree(erandom_state->buf); -+ kfree(erandom_state); -+ -+ unregister_chrdev(frandom_major, "frandom"); -+} -+ -+ -+static int frandom_init_module(void) -+{ -+ int result, i=0; -+ -+ /* The buffer size MUST be at least 256 bytes, because we assume that -+ minimal length in init_rand_state(). -+ */ -+ if (frandom_bufsize < 256) { -+ printk(KERN_ERR "frandom: Refused to load because frandom_bufsize=%d < 256\n",frandom_bufsize); -+ return -EINVAL; -+ } -+ if ((frandom_chunklimit != 0) && (frandom_chunklimit < 256)) { -+ printk(KERN_ERR "frandom: Refused to load because frandom_chunklimit=%d < 256 and != 0\n",frandom_chunklimit); -+ return -EINVAL; -+ } -+ -+ erandom_state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); -+ if (!erandom_state) -+ return -ENOMEM; -+ -+ /* This specific buffer is only used for seeding, so we need -+ 256 bytes exactly */ -+ erandom_state->buf = kmalloc(256, GFP_KERNEL); -+ if (!erandom_state->buf) { -+ kfree(erandom_state); -+ return -ENOMEM; -+ } -+ -+ sema_init(&erandom_state->sem, 1); /* Init semaphore as a mutex */ -+ -+ erandom_seeded = 0; -+ -+#ifdef SET_MODULE_OWNER -+ SET_MODULE_OWNER(&frandom_fops); -+#endif -+ /* -+ * Register your major, and accept a dynamic number. This is the -+ * first thing to do, in order to avoid releasing other module's -+ * fops in frandom_cleanup_module() -+ */ -+ result = register_chrdev(frandom_major, "frandom", &frandom_fops); -+ if (result < 0) { -+ printk(KERN_WARNING "frandom: can't get major %d\n",frandom_major); -+ -+ kfree(erandom_state->buf); -+ kfree(erandom_state); -+ -+ return result; -+ } -+ if (frandom_major == 0) frandom_major = result; /* dynamic */ -+ -+ frandom_class = class_simple_create(THIS_MODULE, "frandom"); -+ for (i = 0; i < ARRAY_SIZE(devlist); i++) { -+ class_simple_device_add(frandom_class, -+ MKDEV(FRANDOM_MAJOR, devlist[i].minor), -+ NULL, devlist[i].name); -+ devfs_mk_cdev(MKDEV(FRANDOM_MAJOR, devlist[i].minor), -+ S_IFCHR | devlist[i].mode, devlist[i].name); -+ } -+ -+ return 0; /* succeed */ -+} -+ -+module_init(frandom_init_module); -+module_exit(frandom_cleanup_module); -+ -+EXPORT_SYMBOL(erandom_get_random_bytes); -diff -Naur linux-2.6.10.orig/drivers/char/random.c linux-2.6.10/drivers/char/random.c ---- linux-2.6.10.orig/drivers/char/random.c 2004-12-24 21:33:51.000000000 +0000 -+++ linux-2.6.10/drivers/char/random.c 2005-02-11 13:12:48.400315968 +0000 -@@ -1994,6 +1994,104 @@ - return 1; - } - -+#ifdef CONFIG_SYSCTL_URANDOM -+static int proc_do_urandom(ctl_table *table, int write, struct file *filp, -+ void *buffer, size_t *lenp, loff_t *ppos) -+{ -+ ctl_table fake_table; -+ unsigned char buf[64], random[16], *p; -+ int i; -+ -+ get_random_bytes(random, 16); -+ -+ p=buf; -+ -+ for (i=0; i<16; i++) { -+ sprintf(p, "%02x", random[i]); -+ p+=2; -+ } -+ -+ fake_table.data = buf; -+ fake_table.maxlen = sizeof(buf); -+ -+ return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos); -+} -+ -+static int urandom_strategy(ctl_table *table, int *name, int nlen, -+ void *oldval, size_t *oldlenp, -+ void *newval, size_t newlen, void **context) -+{ -+ unsigned char random[16]; -+ unsigned int len; -+ -+ if (!oldval || !oldlenp) -+ return 1; -+ -+ get_random_bytes(random, 16); -+ -+ if (get_user(len, oldlenp)) -+ return -EFAULT; -+ if (len) { -+ if (len > 16) -+ len = 16; -+ if (copy_to_user(oldval, random, len) || -+ put_user(len, oldlenp)) -+ return -EFAULT; -+ } -+ return 1; -+} -+#endif -+ -+#ifdef CONFIG_FRANDOM -+void erandom_get_random_bytes(char *buf, size_t count); -+ -+static int proc_do_erandom(ctl_table *table, int write, struct file *filp, -+ void *buffer, size_t *lenp, loff_t *ppos) -+{ -+ ctl_table fake_table; -+ unsigned char buf[64], random[16], *p; -+ int i; -+ -+ erandom_get_random_bytes(random, 16); -+ -+ p=buf; -+ -+ for (i=0; i<16; i++) { -+ sprintf(p, "%02x", random[i]); -+ p+=2; -+ } -+ -+ fake_table.data = buf; -+ fake_table.maxlen = sizeof(buf); -+ -+ return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos); -+} -+ -+static int erandom_strategy(ctl_table *table, int *name, int nlen, -+ void *oldval, size_t *oldlenp, -+ void *newval, size_t newlen, void **context) -+{ -+ unsigned char random[16]; -+ unsigned int len; -+ -+ if (!oldval || !oldlenp) -+ return 1; -+ -+ erandom_get_random_bytes(random, 16); -+ -+ if (get_user(len, oldlenp)) -+ return -EFAULT; -+ if (len) { -+ if (len > 16) -+ len = 16; -+ if (copy_to_user(oldval, random, len) || -+ put_user(len, oldlenp)) -+ return -EFAULT; -+ } -+ return 1; -+} -+#endif -+ - ctl_table random_table[] = { - { - .ctl_name = RANDOM_POOLSIZE, -@@ -2050,6 +2148,26 @@ - .proc_handler = &proc_do_uuid, - .strategy = &uuid_strategy, - }, -+#ifdef CONFIG_SYSCTL_URANDOM -+ { -+ .ctl_name = RANDOM_URANDOM, -+ .procname = "urandom", -+ .maxlen = 16, -+ .mode = 0444, -+ .proc_handler = &proc_do_urandom, -+ .strategy = &urandom_strategy, -+ }, -+#endif -+#ifdef CONFIG_FRANDOM -+ { -+ .ctl_name = RANDOM_ERANDOM, -+ .procname = "erandom", -+ .maxlen = 16, -+ .mode = 0444, -+ .proc_handler = &proc_do_erandom, -+ .strategy = &erandom_strategy, -+ }, -+#endif - { .ctl_name = 0 } - }; - -diff -Naur linux-2.6.10.orig/include/linux/sysctl.h linux-2.6.10/include/linux/sysctl.h ---- linux-2.6.10.orig/include/linux/sysctl.h 2004-12-24 21:34:58.000000000 +0000 -+++ linux-2.6.10/include/linux/sysctl.h 2005-02-10 00:57:23.071640864 +0000 -@@ -194,6 +194,8 @@ - }; - - /* /proc/sys/kernel/random */ -+#define SYSCTL_URANDOM -+#define SYSCTL_ERANDOM - enum - { - RANDOM_POOLSIZE=1, -@@ -201,7 +203,9 @@ - RANDOM_READ_THRESH=3, - RANDOM_WRITE_THRESH=4, - RANDOM_BOOT_ID=5, -- RANDOM_UUID=6 -+ RANDOM_UUID=6, -+ RANDOM_URANDOM=7, -+ RANDOM_ERANDOM=8 - }; - - /* /proc/sys/kernel/pty */ -diff -Naur linux-2.6.10.orig/init/Kconfig linux-2.6.10/init/Kconfig ---- linux-2.6.10.orig/init/Kconfig 2004-12-24 21:35:24.000000000 +0000 -+++ linux-2.6.10/init/Kconfig 2005-02-11 13:17:10.498718928 +0000 -@@ -154,6 +154,16 @@ - building a kernel for install/rescue disks or your system is very - limited in memory. - -+config SYSCTL_URANDOM -+ bool "Sysctl urandom support" -+ depends on SYSCTL -+ default y -+ ---help--- -+ If you say Y here, hooks will be enabled to access get_random_bytes() -+ from sysctl kernel.random.urandom. This is a non-blocking interface. -+ The main advantage to this is to be able to access urandom through -+ a chroot. -+ - config AUDIT - bool "Auditing support" - default y if SECURITY_SELINUX Added: trunk/hlfs/linux-2.6.11-pseudo_random-1.patch =================================================================== --- trunk/hlfs/linux-2.6.11-pseudo_random-1.patch 2005-03-05 14:36:41 UTC (rev 855) +++ trunk/hlfs/linux-2.6.11-pseudo_random-1.patch 2005-03-05 14:39:10 UTC (rev 856) @@ -0,0 +1,617 @@ +Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes) +Date: 2005-03-04 +Initial Package Version: 2.6.11 +Upstream Status: Not submitted +Origin: http://frandom.sourceforge.net/ +Description: This patch adds the he frandom, and erandom devices, and a +sysctl interface for urandom. Udev's permissions need modifications to add +/dev/frandom and /dev/erandom. + +Also see: +http://www.linuxfromscratch.org/hlfs/ +http://www.linuxfromscratch.org/hints/downloads/files/entropy.txt + +diff -Naur linux-2.6.11.orig/drivers/char/Kconfig linux-2.6.11/drivers/char/Kconfig +--- linux-2.6.11.orig/drivers/char/Kconfig 2005-03-04 21:15:42.519856480 +0000 ++++ linux-2.6.11/drivers/char/Kconfig 2005-03-04 21:15:47.952030664 +0000 +@@ -57,6 +57,19 @@ + + If unsure, say Y. + ++config FRANDOM ++ tristate "Fast random data generator suite (/dev/frandom and /dev/erandom)" ++ default y ++ ---help--- ++ Fast random data/number generator support in kernel. This random ++ generator is 10-50 times faster than /dev/urandom, and saves kernel ++ entropy. ++ ++ If unsure, say Y unless you're tight on kernel size. This module is ++ small and harmless otherwise. ++ ++ If you choose M, the sysctl interface will be disabled. ++ + config HW_CONSOLE + bool + depends on VT && !S390 && !USERMODE +diff -Naur linux-2.6.11.orig/drivers/char/Makefile linux-2.6.11/drivers/char/Makefile +--- linux-2.6.11.orig/drivers/char/Makefile 2005-03-04 21:15:42.529854960 +0000 ++++ linux-2.6.11/drivers/char/Makefile 2005-03-04 21:15:47.952030664 +0000 +@@ -9,6 +9,8 @@ + + obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o + ++obj-$(CONFIG_FRANDOM) += frandom.o ++ + obj-$(CONFIG_LEGACY_PTYS) += pty.o + obj-$(CONFIG_UNIX98_PTYS) += pty.o + obj-y += misc.o +diff -Naur linux-2.6.11.orig/drivers/char/frandom.c linux-2.6.11/drivers/char/frandom.c +--- linux-2.6.11.orig/drivers/char/frandom.c 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.11/drivers/char/frandom.c 2005-03-04 21:15:47.953030512 +0000 +@@ -0,0 +1,387 @@ ++/* ++** frandom.c ++** Fast pseudo-random generator ++** ++** (c) Copyright 2003 Eli Billauer ++** http://www.billauer.co.il ++** ++** This program is free software; you can redistribute it and/or modify ++** it under the terms of the GNU General Public License as published by ++** the Free Software Foundation; either version 2 of the License, or ++** (at your option) any later version. ++** ++** Usage: mknod /dev/frandom c 235 11 ++** mknod /dev/erandom c 235 12 ++** insmod frandom ++** ++** This code is highly based upon the examples given in the book "Linux ++** Device Drivers" by Alessandro Rubini and Jonathan Corbet, published ++** by O'Reilly & Associates. ++** O'Reilly's release of this book on the web for free is highly ++** appreciated. ++** ++*/ ++ ++#include <linux/version.h> ++#include <linux/config.h> ++#include <linux/module.h> ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/fs.h> ++#include <linux/errno.h> ++#include <linux/types.h> ++#include <linux/random.h> ++ ++#include <linux/devfs_fs_kernel.h> ++#include <linux/device.h> ++ ++#include <asm/uaccess.h> ++ ++#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,0)) ++#include <linux/moduleparam.h> ++#endif ++ ++#define INTERNAL_SEED 0 ++#define EXTERNAL_SEED 1 ++ ++#define FRANDOM_MAJOR 235 ++#define FRANDOM_MINOR 11 ++#define ERANDOM_MINOR 12 ++ ++static struct file_operations frandom_fops; /* Values assigned below */ ++ ++static int erandom_seeded = 0; /* Internal flag */ ++ ++static int frandom_major = FRANDOM_MAJOR; ++static int frandom_minor = FRANDOM_MINOR; ++static int erandom_minor = ERANDOM_MINOR; ++static int frandom_bufsize = 256; ++static int frandom_chunklimit = 0; /* =0 means unlimited */ ++ ++MODULE_DESCRIPTION("Fast pseudo-random number generator"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Eli Billauer"); ++MODULE_PARM(frandom_major,"i"); ++MODULE_PARM_DESC(frandom_major,"Major number of /dev/frandom and /dev/erandom"); ++MODULE_PARM(frandom_minor,"i"); ++MODULE_PARM_DESC(frandom_minor,"Minor number of /dev/frandom"); ++MODULE_PARM(erandom_minor,"i"); ++MODULE_PARM_DESC(erandom_minor,"Minor number of /dev/erandom"); ++MODULE_PARM(frandom_bufsize,"i"); ++MODULE_PARM_DESC(frandom_bufsize,"Internal buffer size in bytes. Default is 256. Must be >= 256"); ++MODULE_PARM(frandom_chunklimit,"i"); ++MODULE_PARM_DESC(frandom_chunklimit,"Limit for read() blocks size. 0 (default) is unlimited, otherwise must be >= 256"); ++ ++struct frandom_state ++{ ++ struct semaphore sem; /* Semaphore on the state structure */ ++ ++ u8 S[256]; /* The state array */ ++ u8 i; ++ u8 j; ++ ++ char *buf; ++}; ++ ++static struct frandom_state *erandom_state; ++ ++static inline void swap_byte(u8 *a, u8 *b) ++{ ++ u8 swapByte; ++ ++ swapByte = *a; ++ *a = *b; ++ *b = swapByte; ++} ++ ++static void init_rand_state(struct frandom_state *state, int seedflag); ++ ++void erandom_get_random_bytes(char *buf, size_t count) ++{ ++ struct frandom_state *state = erandom_state; ++ int k; ++ ++ unsigned int i; ++ unsigned int j; ++ u8 *S; ++ ++ /* If we fail to get the semaphore, we revert to external random data. ++ Since semaphore blocking is expected to be very rare, and interrupts ++ during these rare and very short periods of time even less frequent, ++ we take the better-safe-than-sorry approach, and fill the buffer ++ some expensive random data, in case the caller wasn't aware of this ++ possibility, and expects random data anyhow. ++ */ ++ ++ if (down_interruptible(&state->sem)) { ++ get_random_bytes(buf, count); ++ return; ++ } ++ ++ /* We seed erandom as late as possible, hoping that the kernel's main ++ RNG is already restored in the boot sequence (not critical, but ++ better. ++ */ ++ ++ if (!erandom_seeded) { ++ erandom_seeded = 1; ++ init_rand_state(state, EXTERNAL_SEED); ++ printk(KERN_INFO "frandom: Seeded global generator now (used by erandom)\n"); ++ } ++ ++ i = state->i; ++ j = state->j; ++ S = state->S; ++ ++ for (k=0; k<count; k++) { ++ i = (i + 1) & 0xff; ++ j = (j + S[i]) & 0xff; ++ swap_byte(&S[i], &S[j]); ++ *buf++ = S[(S[i] + S[j]) & 0xff]; ++ } ++ ++ state->i = i; ++ state->j = j; ++ ++ up(&state->sem); ++} ++ ++static void init_rand_state(struct frandom_state *state, int seedflag) ++{ ++ unsigned int i, j, k; ++ u8 *S; ++ u8 *seed = state->buf; ++ ++ if (seedflag == INTERNAL_SEED) ++ erandom_get_random_bytes(seed, 256); ++ else ++ get_random_bytes(seed, 256); ++ ++ S = state->S; ++ for (i=0; i<256; i++) ++ *S++=i; ++ ++ j=0; ++ S = state->S; ++ ++ for (i=0; i<256; i++) { ++ j = (j + S[i] + *seed++) & 0xff; ++ swap_byte(&S[i], &S[j]); ++ } ++ ++ /* It's considered good practice to discard the first 256 bytes ++ generated. So we do it: ++ */ ++ ++ i=0; j=0; ++ for (k=0; k<256; k++) { ++ i = (i + 1) & 0xff; ++ j = (j + S[i]) & 0xff; ++ swap_byte(&S[i], &S[j]); ++ } ++ ++ state->i = i; /* Save state */ ++ state->j = j; ++} ++ ++static int frandom_open(struct inode *inode, struct file *filp) ++{ ++ ++ struct frandom_state *state; ++ ++ int num =MINOR(inode->i_rdev); ++ if ((num != frandom_minor) && (num != erandom_minor)) return -ENODEV; ++ ++ state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); ++ if (!state) ++ return -ENOMEM; ++ ++ state->buf = kmalloc(frandom_bufsize, GFP_KERNEL); ++ if (!state->buf) { ++ kfree(state); ++ return -ENOMEM; ++ } ++ ++ sema_init(&state->sem, 1); /* Init semaphore as a mutex */ ++ ++ if (num == frandom_minor) ++ init_rand_state(state, EXTERNAL_SEED); ++ else ++ init_rand_state(state, INTERNAL_SEED); ++ ++ filp->private_data = state; ++ ++#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0)) ++ MOD_INC_USE_COUNT; ++#endif ++ ++ return 0; /* Success */ ++} ++ ++static int frandom_release(struct inode *inode, struct file *filp) ++{ ++ ++ struct frandom_state *state = filp->private_data; ++ ++ kfree(state->buf); ++ kfree(state); ++ ++#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0)) ++ MOD_DEC_USE_COUNT; ++#endif ++ ++ return 0; ++} ++ ++static ssize_t frandom_read(struct file *filp, char *buf, size_t count, ++ loff_t *f_pos) ++{ ++ struct frandom_state *state = filp->private_data; ++ ssize_t ret; ++ int dobytes, k; ++ char *localbuf; ++ ++ unsigned int i; ++ unsigned int j; ++ u8 *S; ++ ++ if (down_interruptible(&state->sem)) ++ return -ERESTARTSYS; ++ ++ if ((frandom_chunklimit > 0) && (count > frandom_chunklimit)) ++ count = frandom_chunklimit; ++ ++ ret = count; /* It's either everything or an error... */ ++ ++ i = state->i; ++ j = state->j; ++ S = state->S; ++ ++ while (count) { ++ if (count > frandom_bufsize) ++ dobytes = frandom_bufsize; ++ else ++ dobytes = count; ++ ++ localbuf = state->buf; ++ ++ for (k=0; k<dobytes; k++) { ++ i = (i + 1) & 0xff; ++ j = (j + S[i]) & 0xff; ++ swap_byte(&S[i], &S[j]); ++ *localbuf++ = S[(S[i] + S[j]) & 0xff]; ++ } ++ ++ if (copy_to_user(buf, state->buf, dobytes)) { ++ ret = -EFAULT; ++ goto out; ++ } ++ ++ buf += dobytes; ++ count -= dobytes; ++ } ++ ++ out: ++ state->i = i; ++ state->j = j; ++ ++ up(&state->sem); ++ return ret; ++} ++ ++static struct file_operations frandom_fops = { ++ read: frandom_read, ++ open: frandom_open, ++ release: frandom_release, ++}; ++ ++static const struct { ++ unsigned int minor; ++ char *name; ++ umode_t mode; ++ struct file_operations *fops; ++} devlist[] = { ++ {11, "frandom", S_IRUGO | S_IWUSR, &frandom_fops}, ++ /* Erandom doesn't have its own fop, it shares one with frandom. */ ++ {12, "erandom", S_IRUGO | S_IWUSR, &frandom_fops}, ++}; ++ ++static struct class_simple *frandom_class; ++ ++static void frandom_cleanup_module(void) { ++ kfree(erandom_state->buf); ++ kfree(erandom_state); ++ ++ unregister_chrdev(frandom_major, "frandom"); ++} ++ ++ ++static int frandom_init_module(void) ++{ ++ int result, i=0; ++ ++ /* The buffer size MUST be at least 256 bytes, because we assume that ++ minimal length in init_rand_state(). ++ */ ++ if (frandom_bufsize < 256) { ++ printk(KERN_ERR "frandom: Refused to load because frandom_bufsize=%d < 256\n",frandom_bufsize); ++ return -EINVAL; ++ } ++ if ((frandom_chunklimit != 0) && (frandom_chunklimit < 256)) { ++ printk(KERN_ERR "frandom: Refused to load because frandom_chunklimit=%d < 256 and != 0\n",frandom_chunklimit); ++ return -EINVAL; ++ } ++ ++ erandom_state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); ++ if (!erandom_state) ++ return -ENOMEM; ++ ++ /* This specific buffer is only used for seeding, so we need ++ 256 bytes exactly */ ++ erandom_state->buf = kmalloc(256, GFP_KERNEL); ++ if (!erandom_state->buf) { ++ kfree(erandom_state); ++ return -ENOMEM; ++ } ++ ++ sema_init(&erandom_state->sem, 1); /* Init semaphore as a mutex */ ++ ++ erandom_seeded = 0; ++ ++#ifdef SET_MODULE_OWNER ++ SET_MODULE_OWNER(&frandom_fops); ++#endif ++ /* ++ * Register your major, and accept a dynamic number. This is the ++ * first thing to do, in order to avoid releasing other module's ++ * fops in frandom_cleanup_module() ++ */ ++ result = register_chrdev(frandom_major, "frandom", &frandom_fops); ++ if (result < 0) { ++ printk(KERN_WARNING "frandom: can't get major %d\n",frandom_major); ++ ++ kfree(erandom_state->buf); ++ kfree(erandom_state); ++ ++ return result; ++ } ++ if (frandom_major == 0) frandom_major = result; /* dynamic */ ++ ++ frandom_class = class_simple_create(THIS_MODULE, "frandom"); ++ for (i = 0; i < ARRAY_SIZE(devlist); i++) { ++ class_simple_device_add(frandom_class, ++ MKDEV(FRANDOM_MAJOR, devlist[i].minor), ++ NULL, devlist[i].name); ++ devfs_mk_cdev(MKDEV(FRANDOM_MAJOR, devlist[i].minor), ++ S_IFCHR | devlist[i].mode, devlist[i].name); ++ } ++ ++ return 0; /* succeed */ ++} ++ ++module_init(frandom_init_module); ++module_exit(frandom_cleanup_module); ++ ++EXPORT_SYMBOL(erandom_get_random_bytes); +diff -Naur linux-2.6.11.orig/drivers/char/random.c linux-2.6.11/drivers/char/random.c +--- linux-2.6.11.orig/drivers/char/random.c 2005-03-04 21:15:42.519856480 +0000 ++++ linux-2.6.11/drivers/char/random.c 2005-03-04 21:36:36.799177040 +0000 +@@ -1891,6 +1891,104 @@ + return 1; + } + ++#ifdef CONFIG_SYSCTL_URANDOM ++static int proc_do_urandom(ctl_table *table, int write, struct file *filp, ++ void *buffer, size_t *lenp, loff_t *ppos) ++{ ++ ctl_table fake_table; ++ unsigned char buf[64], random[16], *p; ++ int i; ++ ++ get_random_bytes(random, 16); ++ ++ p=buf; ++ ++ for (i=0; i<16; i++) { ++ sprintf(p, "%02x", random[i]); ++ p+=2; ++ } ++ ++ fake_table.data = buf; ++ fake_table.maxlen = sizeof(buf); ++ ++ return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos); ++} ++ ++static int urandom_strategy(ctl_table *table, int *name, int nlen, ++ void *oldval, size_t *oldlenp, ++ void *newval, size_t newlen, void **context) ++{ ++ unsigned char random[16]; ++ unsigned int len; ++ ++ if (!oldval || !oldlenp) ++ return 1; ++ ++ get_random_bytes(random, 16); ++ ++ if (get_user(len, oldlenp)) ++ return -EFAULT; ++ if (len) { ++ if (len > 16) ++ len = 16; ++ if (copy_to_user(oldval, random, len) || ++ put_user(len, oldlenp)) ++ return -EFAULT; ++ } ++ return 1; ++} ++#endif ++ ++#ifdef CONFIG_FRANDOM ++void erandom_get_random_bytes(char *buf, size_t count); ++ ++static int proc_do_erandom(ctl_table *table, int write, struct file *filp, ++ void *buffer, size_t *lenp, loff_t *ppos) ++{ ++ ctl_table fake_table; ++ unsigned char buf[64], random[16], *p; ++ int i; ++ ++ erandom_get_random_bytes(random, 16); ++ ++ p=buf; ++ ++ for (i=0; i<16; i++) { ++ sprintf(p, "%02x", random[i]); ++ p+=2; ++ } ++ ++ fake_table.data = buf; ++ fake_table.maxlen = sizeof(buf); ++ ++ return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos); ++} ++ ++static int erandom_strategy(ctl_table *table, int *name, int nlen, ++ void *oldval, size_t *oldlenp, ++ void *newval, size_t newlen, void **context) ++{ ++ unsigned char random[16]; ++ unsigned int len; ++ ++ if (!oldval || !oldlenp) ++ return 1; ++ ++ erandom_get_random_bytes(random, 16); ++ ++ if (get_user(len, oldlenp)) ++ return -EFAULT; ++ if (len) { ++ if (len > 16) ++ len = 16; ++ if (copy_to_user(oldval, random, len) || ++ put_user(len, oldlenp)) ++ return -EFAULT; ++ } ++ return 1; ++} ++#endif ++ + static int sysctl_poolsize = DEFAULT_POOL_SIZE; + ctl_table random_table[] = { + { +@@ -1947,6 +2045,26 @@ + .proc_handler = &proc_do_uuid, + .strategy = &uuid_strategy, + }, ++#ifdef CONFIG_SYSCTL_URANDOM ++ { ++ .ctl_name = RANDOM_URANDOM, ++ .procname = "urandom", ++ .maxlen = 16, ++ .mode = 0444, ++ .proc_handler = &proc_do_urandom, ++ .strategy = &urandom_strategy, ++ }, ++#endif ++#ifdef CONFIG_FRANDOM ++ { ++ .ctl_name = RANDOM_ERANDOM, ++ .procname = "erandom", ++ .maxlen = 16, ++ .mode = 0444, ++ .proc_handler = &proc_do_erandom, ++ .strategy = &erandom_strategy, ++ }, ++#endif + { .ctl_name = 0 } + }; + +diff -Naur linux-2.6.11.orig/include/linux/sysctl.h linux-2.6.11/include/linux/sysctl.h +--- linux-2.6.11.orig/include/linux/sysctl.h 2005-03-04 21:15:46.306280856 +0000 ++++ linux-2.6.11/include/linux/sysctl.h 2005-03-04 21:15:47.957029904 +0000 +@@ -195,6 +195,8 @@ + }; + + /* /proc/sys/kernel/random */ ++#define SYSCTL_URANDOM ++#define SYSCTL_ERANDOM + enum + { + RANDOM_POOLSIZE=1, +@@ -202,7 +204,9 @@ + RANDOM_READ_THRESH=3, + RANDOM_WRITE_THRESH=4, + RANDOM_BOOT_ID=5, +- RANDOM_UUID=6 ++ RANDOM_UUID=6, ++ RANDOM_URANDOM=7, ++ RANDOM_ERANDOM=8 + }; + + /* /proc/sys/kernel/pty */ +diff -Naur linux-2.6.11.orig/init/Kconfig linux-2.6.11/init/Kconfig +--- linux-2.6.11.orig/init/Kconfig 2005-03-04 21:15:47.933033552 +0000 ++++ linux-2.6.11/init/Kconfig 2005-03-04 21:15:47.957029904 +0000 +@@ -154,6 +154,16 @@ + building a kernel for install/rescue disks or your system is very + limited in memory. + ++config SYSCTL_URANDOM ++ bool "Sysctl urandom support" ++ depends on SYSCTL ++ default y ++ ---help--- ++ If you say Y here, hooks will be enabled to access get_random_bytes() ++ from sysctl kernel.random.urandom. This is a non-blocking interface. ++ The main advantage to this is to be able to access urandom through ++ a chroot. ++ + config AUDIT + bool "Auditing support" + default y if SECURITY_SELINUX Deleted: trunk/linux/linux-2.6.10-pseudo_random-1.patch =================================================================== --- trunk/linux/linux-2.6.10-pseudo_random-1.patch 2005-03-05 14:36:41 UTC (rev 855) +++ trunk/linux/linux-2.6.10-pseudo_random-1.patch 2005-03-05 14:39:10 UTC (rev 856) @@ -1 +0,0 @@ -link ../hlfs/linux-2.6.10-pseudo_random-1.patch \ No newline at end of file Added: trunk/linux/linux-2.6.11-pseudo_random-1.patch =================================================================== --- trunk/linux/linux-2.6.11-pseudo_random-1.patch 2005-03-05 14:36:41 UTC (rev 855) +++ trunk/linux/linux-2.6.11-pseudo_random-1.patch 2005-03-05 14:39:10 UTC (rev 856) @@ -0,0 +1 @@ +link ../hlfs/linux-2.6.11-pseudo_random-1.patch \ No newline at end of file Property changes on: trunk/linux/linux-2.6.11-pseudo_random-1.patch ___________________________________________________________________ Name: svn:special + * -- http://linuxfromscratch.org/mailman/listinfo/patches FAQ: http://www.linuxfromscratch.org/faq/ Unsubscribe: See the above information page
