aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorMatt Mackall <mpm@selenic.com>2007-05-29 22:58:10 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-29 23:09:34 -0400
commit7f397dcdb78d699a20d96bfcfb595a2411a5bbd2 (patch)
tree7ecb0b2f782a4e18eef80ff638f0469cd4ad0233 /drivers/char
parent602b6aeefe8932dd8bb15014e8fe6bb25d736361 (diff)
random: fix seeding with zero entropy
Add data from zero-entropy random_writes directly to output pools to avoid accounting difficulties on machines without entropy sources. Tested on lguest with all entropy sources disabled. Signed-off-by: Matt Mackall <mpm@selenic.com> Acked-by: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/random.c55
1 files changed, 31 insertions, 24 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 9705b439448a..0474cac4a84e 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1020,37 +1020,44 @@ random_poll(struct file *file, poll_table * wait)
1020 return mask; 1020 return mask;
1021} 1021}
1022 1022
1023static ssize_t 1023static int
1024random_write(struct file * file, const char __user * buffer, 1024write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
1025 size_t count, loff_t *ppos)
1026{ 1025{
1027 int ret = 0;
1028 size_t bytes; 1026 size_t bytes;
1029 __u32 buf[16]; 1027 __u32 buf[16];
1030 const char __user *p = buffer; 1028 const char __user *p = buffer;
1031 size_t c = count;
1032 1029
1033 while (c > 0) { 1030 while (count > 0) {
1034 bytes = min(c, sizeof(buf)); 1031 bytes = min(count, sizeof(buf));
1032 if (copy_from_user(&buf, p, bytes))
1033 return -EFAULT;
1035 1034
1036 bytes -= copy_from_user(&buf, p, bytes); 1035 count -= bytes;
1037 if (!bytes) {
1038 ret = -EFAULT;
1039 break;
1040 }
1041 c -= bytes;
1042 p += bytes; 1036 p += bytes;
1043 1037
1044 add_entropy_words(&input_pool, buf, (bytes + 3) / 4); 1038 add_entropy_words(r, buf, (bytes + 3) / 4);
1045 }
1046 if (p == buffer) {
1047 return (ssize_t)ret;
1048 } else {
1049 struct inode *inode = file->f_path.dentry->d_inode;
1050 inode->i_mtime = current_fs_time(inode->i_sb);
1051 mark_inode_dirty(inode);
1052 return (ssize_t)(p - buffer);
1053 } 1039 }
1040
1041 return 0;
1042}
1043
1044static ssize_t
1045random_write(struct file * file, const char __user * buffer,
1046 size_t count, loff_t *ppos)
1047{
1048 size_t ret;
1049 struct inode *inode = file->f_path.dentry->d_inode;
1050
1051 ret = write_pool(&blocking_pool, buffer, count);
1052 if (ret)
1053 return ret;
1054 ret = write_pool(&nonblocking_pool, buffer, count);
1055 if (ret)
1056 return ret;
1057
1058 inode->i_mtime = current_fs_time(inode->i_sb);
1059 mark_inode_dirty(inode);
1060 return (ssize_t)count;
1054} 1061}
1055 1062
1056static int 1063static int
@@ -1089,8 +1096,8 @@ random_ioctl(struct inode * inode, struct file * file,
1089 return -EINVAL; 1096 return -EINVAL;
1090 if (get_user(size, p++)) 1097 if (get_user(size, p++))
1091 return -EFAULT; 1098 return -EFAULT;
1092 retval = random_write(file, (const char __user *) p, 1099 retval = write_pool(&input_pool, (const char __user *)p,
1093 size, &file->f_pos); 1100 size);
1094 if (retval < 0) 1101 if (retval < 0)
1095 return retval; 1102 return retval;
1096 credit_entropy_store(&input_pool, ent_count); 1103 credit_entropy_store(&input_pool, ent_count);