diff options
author | Christoph Hellwig <hch@lst.de> | 2007-05-08 03:29:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:09 -0400 |
commit | 6272e2667965dfb5b59199f462cd0f001fb304a6 (patch) | |
tree | a14a4537dcd7af09863cc3a1c19a3efe386d67ab /fs/compat.c | |
parent | 039b6b3ed84e45a6f8316358dd2bfdc83d59fc45 (diff) |
cleanup compat ioctl handling
Merge all compat ioctl handling into compat_ioctl.c instead of splitting it
over compat.c and compat_ioctl.c. This also allows to get rid of ioctl32.h
Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks-good-to: Andi Kleen <ak@suse.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 162 |
1 files changed, 1 insertions, 161 deletions
diff --git a/fs/compat.c b/fs/compat.c index a32e2ae737fb..9f6248dfd9d9 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -25,10 +25,8 @@ | |||
25 | #include <linux/namei.h> | 25 | #include <linux/namei.h> |
26 | #include <linux/file.h> | 26 | #include <linux/file.h> |
27 | #include <linux/vfs.h> | 27 | #include <linux/vfs.h> |
28 | #include <linux/ioctl32.h> | ||
29 | #include <linux/ioctl.h> | 28 | #include <linux/ioctl.h> |
30 | #include <linux/init.h> | 29 | #include <linux/init.h> |
31 | #include <linux/sockios.h> /* for SIOCDEVPRIVATE */ | ||
32 | #include <linux/smb.h> | 30 | #include <linux/smb.h> |
33 | #include <linux/smb_mount.h> | 31 | #include <linux/smb_mount.h> |
34 | #include <linux/ncp_mount.h> | 32 | #include <linux/ncp_mount.h> |
@@ -46,13 +44,12 @@ | |||
46 | #include <linux/personality.h> | 44 | #include <linux/personality.h> |
47 | #include <linux/rwsem.h> | 45 | #include <linux/rwsem.h> |
48 | #include <linux/tsacct_kern.h> | 46 | #include <linux/tsacct_kern.h> |
47 | #include <linux/security.h> | ||
49 | #include <linux/highmem.h> | 48 | #include <linux/highmem.h> |
50 | #include <linux/poll.h> | 49 | #include <linux/poll.h> |
51 | #include <linux/mm.h> | 50 | #include <linux/mm.h> |
52 | #include <linux/eventpoll.h> | 51 | #include <linux/eventpoll.h> |
53 | 52 | ||
54 | #include <net/sock.h> /* siocdevprivate_ioctl */ | ||
55 | |||
56 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
57 | #include <asm/mmu_context.h> | 54 | #include <asm/mmu_context.h> |
58 | #include <asm/ioctls.h> | 55 | #include <asm/ioctls.h> |
@@ -313,163 +310,6 @@ out: | |||
313 | return error; | 310 | return error; |
314 | } | 311 | } |
315 | 312 | ||
316 | /* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */ | ||
317 | |||
318 | #define IOCTL_HASHSIZE 256 | ||
319 | static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; | ||
320 | |||
321 | static inline unsigned long ioctl32_hash(unsigned long cmd) | ||
322 | { | ||
323 | return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE; | ||
324 | } | ||
325 | |||
326 | static void ioctl32_insert_translation(struct ioctl_trans *trans) | ||
327 | { | ||
328 | unsigned long hash; | ||
329 | struct ioctl_trans *t; | ||
330 | |||
331 | hash = ioctl32_hash (trans->cmd); | ||
332 | if (!ioctl32_hash_table[hash]) | ||
333 | ioctl32_hash_table[hash] = trans; | ||
334 | else { | ||
335 | t = ioctl32_hash_table[hash]; | ||
336 | while (t->next) | ||
337 | t = t->next; | ||
338 | trans->next = NULL; | ||
339 | t->next = trans; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | static int __init init_sys32_ioctl(void) | ||
344 | { | ||
345 | int i; | ||
346 | |||
347 | for (i = 0; i < ioctl_table_size; i++) { | ||
348 | if (ioctl_start[i].next != 0) { | ||
349 | printk("ioctl translation %d bad\n",i); | ||
350 | return -1; | ||
351 | } | ||
352 | |||
353 | ioctl32_insert_translation(&ioctl_start[i]); | ||
354 | } | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | __initcall(init_sys32_ioctl); | ||
359 | |||
360 | static void compat_ioctl_error(struct file *filp, unsigned int fd, | ||
361 | unsigned int cmd, unsigned long arg) | ||
362 | { | ||
363 | char buf[10]; | ||
364 | char *fn = "?"; | ||
365 | char *path; | ||
366 | |||
367 | /* find the name of the device. */ | ||
368 | path = (char *)__get_free_page(GFP_KERNEL); | ||
369 | if (path) { | ||
370 | fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE); | ||
371 | if (IS_ERR(fn)) | ||
372 | fn = "?"; | ||
373 | } | ||
374 | |||
375 | sprintf(buf,"'%c'", (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK); | ||
376 | if (!isprint(buf[1])) | ||
377 | sprintf(buf, "%02x", buf[1]); | ||
378 | compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) " | ||
379 | "cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n", | ||
380 | current->comm, current->pid, | ||
381 | (int)fd, (unsigned int)cmd, buf, | ||
382 | (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK, | ||
383 | (unsigned int)arg, fn); | ||
384 | |||
385 | if (path) | ||
386 | free_page((unsigned long)path); | ||
387 | } | ||
388 | |||
389 | asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, | ||
390 | unsigned long arg) | ||
391 | { | ||
392 | struct file *filp; | ||
393 | int error = -EBADF; | ||
394 | struct ioctl_trans *t; | ||
395 | int fput_needed; | ||
396 | |||
397 | filp = fget_light(fd, &fput_needed); | ||
398 | if (!filp) | ||
399 | goto out; | ||
400 | |||
401 | /* RED-PEN how should LSM module know it's handling 32bit? */ | ||
402 | error = security_file_ioctl(filp, cmd, arg); | ||
403 | if (error) | ||
404 | goto out_fput; | ||
405 | |||
406 | /* | ||
407 | * To allow the compat_ioctl handlers to be self contained | ||
408 | * we need to check the common ioctls here first. | ||
409 | * Just handle them with the standard handlers below. | ||
410 | */ | ||
411 | switch (cmd) { | ||
412 | case FIOCLEX: | ||
413 | case FIONCLEX: | ||
414 | case FIONBIO: | ||
415 | case FIOASYNC: | ||
416 | case FIOQSIZE: | ||
417 | break; | ||
418 | |||
419 | case FIBMAP: | ||
420 | case FIGETBSZ: | ||
421 | case FIONREAD: | ||
422 | if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) | ||
423 | break; | ||
424 | /*FALL THROUGH*/ | ||
425 | |||
426 | default: | ||
427 | if (filp->f_op && filp->f_op->compat_ioctl) { | ||
428 | error = filp->f_op->compat_ioctl(filp, cmd, arg); | ||
429 | if (error != -ENOIOCTLCMD) | ||
430 | goto out_fput; | ||
431 | } | ||
432 | |||
433 | if (!filp->f_op || | ||
434 | (!filp->f_op->ioctl && !filp->f_op->unlocked_ioctl)) | ||
435 | goto do_ioctl; | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) { | ||
440 | if (t->cmd == cmd) | ||
441 | goto found_handler; | ||
442 | } | ||
443 | |||
444 | if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) && | ||
445 | cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { | ||
446 | error = siocdevprivate_ioctl(fd, cmd, arg); | ||
447 | } else { | ||
448 | static int count; | ||
449 | |||
450 | if (++count <= 50) | ||
451 | compat_ioctl_error(filp, fd, cmd, arg); | ||
452 | error = -EINVAL; | ||
453 | } | ||
454 | |||
455 | goto out_fput; | ||
456 | |||
457 | found_handler: | ||
458 | if (t->handler) { | ||
459 | lock_kernel(); | ||
460 | error = t->handler(fd, cmd, arg, filp); | ||
461 | unlock_kernel(); | ||
462 | goto out_fput; | ||
463 | } | ||
464 | |||
465 | do_ioctl: | ||
466 | error = vfs_ioctl(filp, fd, cmd, arg); | ||
467 | out_fput: | ||
468 | fput_light(filp, fput_needed); | ||
469 | out: | ||
470 | return error; | ||
471 | } | ||
472 | |||
473 | static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) | 313 | static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) |
474 | { | 314 | { |
475 | if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || | 315 | if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || |