bb0652ef7d7de0ca234236bf23be3c4d585d2de8
[moctel.git] / moctel_mod.c
1 #undef __KERNEL__
2 #define __KERNEL__
3 #undef MODULE
4 #define MODULE
5
6 #include <linux/module.h>
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/file.h>
10 #include <linux/fs.h>
11 #include <linux/ioctl.h>
12 #include <linux/uaccess.h>
13 #include <linux/miscdevice.h>
14
15 struct fetch_fops_args {
16   int fd;
17   u64 retp;
18 };
19
20 #define MOCTEL_FETCH_FOPS _IOR('m', 1, struct fetch_fops_args)
21
22 static int ioctl_open(struct inode *nodp, struct file *filp) {
23   return 0;
24 }
25
26 static const struct file_operations dummy_fops = {};
27
28 static long ioctl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
29   struct fetch_fops_args args;
30   struct fd f;
31   const struct file_operations *fops;
32
33   if (cmd != MOCTEL_FETCH_FOPS) return -EINVAL;
34   if (copy_from_user(&args, (struct fetch_fops_args __user *)arg, sizeof(args))) return -EINVAL;
35   f = fdget(args.fd);
36   if (!f.file) return -EBADF;
37   fops = f.file->f_op;
38   if (!fops) fops = dummy_fops;
39   fdput(f);
40   if (copy_to_user((struct file_operations __user *)args.retp, fops, sizeof(*fops))) return -EINVAL;
41   return 0;
42 }
43
44 static int ioctl_release(struct inode *nodp, struct file *filp) {
45   return 0;
46 }
47
48 static const struct file_operations ioctl_fops = {
49   .owner = THIS_MODULE,
50   .ioctl = ioctl_ioctl, /* I have no idea about locking,
51                            so just take the Big Kernel Lock implicitly. */
52   .open = ioctl_open,
53   .release = ioctl_release
54 };
55
56 static struct miscdevice ioctl_miscdev = {
57   .minor = 0,
58   .name = "ioctl_info",
59   .fops = &ioctl_fops
60 };
61
62 static int __init init_ioctl() {
63   int ret;
64   printk(KERN_INFO "loading ioctl helper\n");
65
66   ret = misc_register(&ioctl_miscdev);
67   return ret;
68 }
69
70 static void __exit cleanup_ioctl() {
71   printk(KERN_INFO "unloading ioctl helper\n");
72   misc_deregister(&ioctl_miscdev);
73 }
74
75 module_init(init_ioctl);
76 module_exit(cleanup_ioctl);