aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2005-12-09 13:21:44 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 22:53:31 -0500
commitf9ce299fc629d5c899a2e56b00e21f5da05cf590 (patch)
treeda8f883f72d08f9534e9eca3bba662413b9bd865
parentd52771fce4e774fa786097d34412a057d487c697 (diff)
[PATCH] powerpc: fix large nvram access
/dev/nvram uses the user-provided read/write size for kmalloc, which fails, if a large number is passed. This will always use a single page at most, which can be expected to succeed. Signed-off-by: Arnd Bergmann <arndb@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/nvram_64.c106
1 files changed, 50 insertions, 56 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index c0fcd29918ce..fd7db8d542db 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -80,80 +80,74 @@ static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
80static ssize_t dev_nvram_read(struct file *file, char __user *buf, 80static ssize_t dev_nvram_read(struct file *file, char __user *buf,
81 size_t count, loff_t *ppos) 81 size_t count, loff_t *ppos)
82{ 82{
83 ssize_t len; 83 ssize_t ret;
84 char *tmp_buffer; 84 char *tmp = NULL;
85 int size; 85 ssize_t size;
86 86
87 if (ppc_md.nvram_size == NULL) 87 ret = -ENODEV;
88 return -ENODEV; 88 if (!ppc_md.nvram_size)
89 goto out;
90
91 ret = 0;
89 size = ppc_md.nvram_size(); 92 size = ppc_md.nvram_size();
93 if (*ppos >= size || size < 0)
94 goto out;
90 95
91 if (!access_ok(VERIFY_WRITE, buf, count)) 96 count = min_t(size_t, count, size - *ppos);
92 return -EFAULT; 97 count = min(count, PAGE_SIZE);
93 if (*ppos >= size)
94 return 0;
95 if (count > size)
96 count = size;
97 98
98 tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); 99 ret = -ENOMEM;
99 if (!tmp_buffer) { 100 tmp = kmalloc(count, GFP_KERNEL);
100 printk(KERN_ERR "dev_read_nvram: kmalloc failed\n"); 101 if (!tmp)
101 return -ENOMEM; 102 goto out;
102 }
103 103
104 len = ppc_md.nvram_read(tmp_buffer, count, ppos); 104 ret = ppc_md.nvram_read(tmp, count, ppos);
105 if ((long)len <= 0) { 105 if (ret <= 0)
106 kfree(tmp_buffer); 106 goto out;
107 return len;
108 }
109 107
110 if (copy_to_user(buf, tmp_buffer, len)) { 108 if (copy_to_user(buf, tmp, ret))
111 kfree(tmp_buffer); 109 ret = -EFAULT;
112 return -EFAULT;
113 }
114 110
115 kfree(tmp_buffer); 111out:
116 return len; 112 kfree(tmp);
113 return ret;
117 114
118} 115}
119 116
120static ssize_t dev_nvram_write(struct file *file, const char __user *buf, 117static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
121 size_t count, loff_t *ppos) 118 size_t count, loff_t *ppos)
122{ 119{
123 ssize_t len; 120 ssize_t ret;
124 char * tmp_buffer; 121 char *tmp = NULL;
125 int size; 122 ssize_t size;
126 123
127 if (ppc_md.nvram_size == NULL) 124 ret = -ENODEV;
128 return -ENODEV; 125 if (!ppc_md.nvram_size)
126 goto out;
127
128 ret = 0;
129 size = ppc_md.nvram_size(); 129 size = ppc_md.nvram_size();
130 if (*ppos >= size || size < 0)
131 goto out;
130 132
131 if (!access_ok(VERIFY_READ, buf, count)) 133 count = min_t(size_t, count, size - *ppos);
132 return -EFAULT; 134 count = min(count, PAGE_SIZE);
133 if (*ppos >= size)
134 return 0;
135 if (count > size)
136 count = size;
137 135
138 tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); 136 ret = -ENOMEM;
139 if (!tmp_buffer) { 137 tmp = kmalloc(count, GFP_KERNEL);
140 printk(KERN_ERR "dev_nvram_write: kmalloc failed\n"); 138 if (!tmp)
141 return -ENOMEM; 139 goto out;
142 }
143
144 if (copy_from_user(tmp_buffer, buf, count)) {
145 kfree(tmp_buffer);
146 return -EFAULT;
147 }
148 140
149 len = ppc_md.nvram_write(tmp_buffer, count, ppos); 141 ret = -EFAULT;
150 if ((long)len <= 0) { 142 if (copy_from_user(tmp, buf, count))
151 kfree(tmp_buffer); 143 goto out;
152 return len; 144
153 } 145 ret = ppc_md.nvram_write(tmp, count, ppos);
146
147out:
148 kfree(tmp);
149 return ret;
154 150
155 kfree(tmp_buffer);
156 return len;
157} 151}
158 152
159static int dev_nvram_ioctl(struct inode *inode, struct file *file, 153static int dev_nvram_ioctl(struct inode *inode, struct file *file,