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