diff options
Diffstat (limited to 'arch/i386/kernel/cpu/mtrr/if.c')
-rw-r--r-- | arch/i386/kernel/cpu/mtrr/if.c | 119 |
1 files changed, 74 insertions, 45 deletions
diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c index 1923e0aed26a..cf39e205d33c 100644 --- a/arch/i386/kernel/cpu/mtrr/if.c +++ b/arch/i386/kernel/cpu/mtrr/if.c | |||
@@ -149,60 +149,89 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos) | |||
149 | return -EINVAL; | 149 | return -EINVAL; |
150 | } | 150 | } |
151 | 151 | ||
152 | static int | 152 | static long |
153 | mtrr_ioctl(struct inode *inode, struct file *file, | 153 | mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) |
154 | unsigned int cmd, unsigned long __arg) | ||
155 | { | 154 | { |
156 | int err; | 155 | int err = 0; |
157 | mtrr_type type; | 156 | mtrr_type type; |
158 | struct mtrr_sentry sentry; | 157 | struct mtrr_sentry sentry; |
159 | struct mtrr_gentry gentry; | 158 | struct mtrr_gentry gentry; |
160 | void __user *arg = (void __user *) __arg; | 159 | void __user *arg = (void __user *) __arg; |
161 | 160 | ||
162 | switch (cmd) { | 161 | switch (cmd) { |
162 | case MTRRIOC_ADD_ENTRY: | ||
163 | case MTRRIOC_SET_ENTRY: | ||
164 | case MTRRIOC_DEL_ENTRY: | ||
165 | case MTRRIOC_KILL_ENTRY: | ||
166 | case MTRRIOC_ADD_PAGE_ENTRY: | ||
167 | case MTRRIOC_SET_PAGE_ENTRY: | ||
168 | case MTRRIOC_DEL_PAGE_ENTRY: | ||
169 | case MTRRIOC_KILL_PAGE_ENTRY: | ||
170 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
171 | return -EFAULT; | ||
172 | break; | ||
173 | case MTRRIOC_GET_ENTRY: | ||
174 | case MTRRIOC_GET_PAGE_ENTRY: | ||
175 | if (copy_from_user(&gentry, arg, sizeof gentry)) | ||
176 | return -EFAULT; | ||
177 | break; | ||
178 | #ifdef CONFIG_COMPAT | ||
179 | case MTRRIOC32_ADD_ENTRY: | ||
180 | case MTRRIOC32_SET_ENTRY: | ||
181 | case MTRRIOC32_DEL_ENTRY: | ||
182 | case MTRRIOC32_KILL_ENTRY: | ||
183 | case MTRRIOC32_ADD_PAGE_ENTRY: | ||
184 | case MTRRIOC32_SET_PAGE_ENTRY: | ||
185 | case MTRRIOC32_DEL_PAGE_ENTRY: | ||
186 | case MTRRIOC32_KILL_PAGE_ENTRY: { | ||
187 | struct mtrr_sentry32 __user *s32 = (struct mtrr_sentry32 __user *)__arg; | ||
188 | err = get_user(sentry.base, &s32->base); | ||
189 | err |= get_user(sentry.size, &s32->size); | ||
190 | err |= get_user(sentry.type, &s32->type); | ||
191 | if (err) | ||
192 | return err; | ||
193 | break; | ||
194 | } | ||
195 | case MTRRIOC32_GET_ENTRY: | ||
196 | case MTRRIOC32_GET_PAGE_ENTRY: { | ||
197 | struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)__arg; | ||
198 | err = get_user(gentry.regnum, &g32->regnum); | ||
199 | err |= get_user(gentry.base, &g32->base); | ||
200 | err |= get_user(gentry.size, &g32->size); | ||
201 | err |= get_user(gentry.type, &g32->type); | ||
202 | if (err) | ||
203 | return err; | ||
204 | break; | ||
205 | } | ||
206 | #endif | ||
207 | } | ||
208 | |||
209 | switch (cmd) { | ||
163 | default: | 210 | default: |
164 | return -ENOTTY; | 211 | return -ENOTTY; |
165 | case MTRRIOC_ADD_ENTRY: | 212 | case MTRRIOC_ADD_ENTRY: |
166 | if (!capable(CAP_SYS_ADMIN)) | 213 | if (!capable(CAP_SYS_ADMIN)) |
167 | return -EPERM; | 214 | return -EPERM; |
168 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
169 | return -EFAULT; | ||
170 | err = | 215 | err = |
171 | mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, | 216 | mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, |
172 | file, 0); | 217 | file, 0); |
173 | if (err < 0) | ||
174 | return err; | ||
175 | break; | 218 | break; |
176 | case MTRRIOC_SET_ENTRY: | 219 | case MTRRIOC_SET_ENTRY: |
177 | if (!capable(CAP_SYS_ADMIN)) | 220 | if (!capable(CAP_SYS_ADMIN)) |
178 | return -EPERM; | 221 | return -EPERM; |
179 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
180 | return -EFAULT; | ||
181 | err = mtrr_add(sentry.base, sentry.size, sentry.type, 0); | 222 | err = mtrr_add(sentry.base, sentry.size, sentry.type, 0); |
182 | if (err < 0) | ||
183 | return err; | ||
184 | break; | 223 | break; |
185 | case MTRRIOC_DEL_ENTRY: | 224 | case MTRRIOC_DEL_ENTRY: |
186 | if (!capable(CAP_SYS_ADMIN)) | 225 | if (!capable(CAP_SYS_ADMIN)) |
187 | return -EPERM; | 226 | return -EPERM; |
188 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
189 | return -EFAULT; | ||
190 | err = mtrr_file_del(sentry.base, sentry.size, file, 0); | 227 | err = mtrr_file_del(sentry.base, sentry.size, file, 0); |
191 | if (err < 0) | ||
192 | return err; | ||
193 | break; | 228 | break; |
194 | case MTRRIOC_KILL_ENTRY: | 229 | case MTRRIOC_KILL_ENTRY: |
195 | if (!capable(CAP_SYS_ADMIN)) | 230 | if (!capable(CAP_SYS_ADMIN)) |
196 | return -EPERM; | 231 | return -EPERM; |
197 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
198 | return -EFAULT; | ||
199 | err = mtrr_del(-1, sentry.base, sentry.size); | 232 | err = mtrr_del(-1, sentry.base, sentry.size); |
200 | if (err < 0) | ||
201 | return err; | ||
202 | break; | 233 | break; |
203 | case MTRRIOC_GET_ENTRY: | 234 | case MTRRIOC_GET_ENTRY: |
204 | if (copy_from_user(&gentry, arg, sizeof gentry)) | ||
205 | return -EFAULT; | ||
206 | if (gentry.regnum >= num_var_ranges) | 235 | if (gentry.regnum >= num_var_ranges) |
207 | return -EINVAL; | 236 | return -EINVAL; |
208 | mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); | 237 | mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); |
@@ -217,60 +246,59 @@ mtrr_ioctl(struct inode *inode, struct file *file, | |||
217 | gentry.type = type; | 246 | gentry.type = type; |
218 | } | 247 | } |
219 | 248 | ||
220 | if (copy_to_user(arg, &gentry, sizeof gentry)) | ||
221 | return -EFAULT; | ||
222 | break; | 249 | break; |
223 | case MTRRIOC_ADD_PAGE_ENTRY: | 250 | case MTRRIOC_ADD_PAGE_ENTRY: |
224 | if (!capable(CAP_SYS_ADMIN)) | 251 | if (!capable(CAP_SYS_ADMIN)) |
225 | return -EPERM; | 252 | return -EPERM; |
226 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
227 | return -EFAULT; | ||
228 | err = | 253 | err = |
229 | mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, | 254 | mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, |
230 | file, 1); | 255 | file, 1); |
231 | if (err < 0) | ||
232 | return err; | ||
233 | break; | 256 | break; |
234 | case MTRRIOC_SET_PAGE_ENTRY: | 257 | case MTRRIOC_SET_PAGE_ENTRY: |
235 | if (!capable(CAP_SYS_ADMIN)) | 258 | if (!capable(CAP_SYS_ADMIN)) |
236 | return -EPERM; | 259 | return -EPERM; |
237 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
238 | return -EFAULT; | ||
239 | err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0); | 260 | err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0); |
240 | if (err < 0) | ||
241 | return err; | ||
242 | break; | 261 | break; |
243 | case MTRRIOC_DEL_PAGE_ENTRY: | 262 | case MTRRIOC_DEL_PAGE_ENTRY: |
244 | if (!capable(CAP_SYS_ADMIN)) | 263 | if (!capable(CAP_SYS_ADMIN)) |
245 | return -EPERM; | 264 | return -EPERM; |
246 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
247 | return -EFAULT; | ||
248 | err = mtrr_file_del(sentry.base, sentry.size, file, 1); | 265 | err = mtrr_file_del(sentry.base, sentry.size, file, 1); |
249 | if (err < 0) | ||
250 | return err; | ||
251 | break; | 266 | break; |
252 | case MTRRIOC_KILL_PAGE_ENTRY: | 267 | case MTRRIOC_KILL_PAGE_ENTRY: |
253 | if (!capable(CAP_SYS_ADMIN)) | 268 | if (!capable(CAP_SYS_ADMIN)) |
254 | return -EPERM; | 269 | return -EPERM; |
255 | if (copy_from_user(&sentry, arg, sizeof sentry)) | ||
256 | return -EFAULT; | ||
257 | err = mtrr_del_page(-1, sentry.base, sentry.size); | 270 | err = mtrr_del_page(-1, sentry.base, sentry.size); |
258 | if (err < 0) | ||
259 | return err; | ||
260 | break; | 271 | break; |
261 | case MTRRIOC_GET_PAGE_ENTRY: | 272 | case MTRRIOC_GET_PAGE_ENTRY: |
262 | if (copy_from_user(&gentry, arg, sizeof gentry)) | ||
263 | return -EFAULT; | ||
264 | if (gentry.regnum >= num_var_ranges) | 273 | if (gentry.regnum >= num_var_ranges) |
265 | return -EINVAL; | 274 | return -EINVAL; |
266 | mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); | 275 | mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); |
267 | gentry.type = type; | 276 | gentry.type = type; |
277 | break; | ||
278 | } | ||
279 | |||
280 | if (err) | ||
281 | return err; | ||
268 | 282 | ||
283 | switch(cmd) { | ||
284 | case MTRRIOC_GET_ENTRY: | ||
285 | case MTRRIOC_GET_PAGE_ENTRY: | ||
269 | if (copy_to_user(arg, &gentry, sizeof gentry)) | 286 | if (copy_to_user(arg, &gentry, sizeof gentry)) |
270 | return -EFAULT; | 287 | err = -EFAULT; |
288 | break; | ||
289 | #ifdef CONFIG_COMPAT | ||
290 | case MTRRIOC32_GET_ENTRY: | ||
291 | case MTRRIOC32_GET_PAGE_ENTRY: { | ||
292 | struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)__arg; | ||
293 | err = put_user(gentry.base, &g32->base); | ||
294 | err |= put_user(gentry.size, &g32->size); | ||
295 | err |= put_user(gentry.regnum, &g32->regnum); | ||
296 | err |= put_user(gentry.type, &g32->type); | ||
271 | break; | 297 | break; |
272 | } | 298 | } |
273 | return 0; | 299 | #endif |
300 | } | ||
301 | return err; | ||
274 | } | 302 | } |
275 | 303 | ||
276 | static int | 304 | static int |
@@ -310,7 +338,8 @@ static struct file_operations mtrr_fops = { | |||
310 | .read = seq_read, | 338 | .read = seq_read, |
311 | .llseek = seq_lseek, | 339 | .llseek = seq_lseek, |
312 | .write = mtrr_write, | 340 | .write = mtrr_write, |
313 | .ioctl = mtrr_ioctl, | 341 | .unlocked_ioctl = mtrr_ioctl, |
342 | .compat_ioctl = mtrr_ioctl, | ||
314 | .release = mtrr_close, | 343 | .release = mtrr_close, |
315 | }; | 344 | }; |
316 | 345 | ||