it works! :)
authorJann Horn <jann@thejh.net>
Sat, 18 May 2013 23:41:57 +0000 (01:41 +0200)
committerJann Horn <jann@thejh.net>
Sat, 18 May 2013 23:41:57 +0000 (01:41 +0200)
.gitignore [new file with mode: 0644]
Makefile
moctel_mod.c
show_ioctl.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..7f3ee05
--- /dev/null
@@ -0,0 +1,8 @@
+show_ioctl
+moctel_mod.ko
+moctel_mod.mod.*
+.tmp_versions
+*.cmd
+modules.order
+*.o
+Module.symvers
index ac7b8da..5516404 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,12 @@
 obj-m := moctel_mod.o
 KDIR := /lib/modules/$(shell uname -r)/build
 PWD := $(shell pwd)
 obj-m := moctel_mod.o
 KDIR := /lib/modules/$(shell uname -r)/build
 PWD := $(shell pwd)
-all:
+
+all: show_ioctl
        $(MAKE) -C $(KDIR) M=$(PWD) modules
        $(MAKE) -C $(KDIR) M=$(PWD) modules
+
+show_ioctl:
+       gcc -o show_ioctl show_ioctl.c -std=gnu99
  
 clean:
        $(MAKE) -C $(KDIR) M=$(PWD) clean
  
 clean:
        $(MAKE) -C $(KDIR) M=$(PWD) clean
index bb0652e..47d63f8 100644 (file)
@@ -25,18 +25,18 @@ static int ioctl_open(struct inode *nodp, struct file *filp) {
 
 static const struct file_operations dummy_fops = {};
 
 
 static const struct file_operations dummy_fops = {};
 
-static long ioctl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
+static long ioctl_ioctl(struct file *filp_, unsigned int cmd, unsigned long arg) {
   struct fetch_fops_args args;
   struct fetch_fops_args args;
-  struct fd f;
+  struct file *filp;
   const struct file_operations *fops;
 
   if (cmd != MOCTEL_FETCH_FOPS) return -EINVAL;
   if (copy_from_user(&args, (struct fetch_fops_args __user *)arg, sizeof(args))) return -EINVAL;
   const struct file_operations *fops;
 
   if (cmd != MOCTEL_FETCH_FOPS) return -EINVAL;
   if (copy_from_user(&args, (struct fetch_fops_args __user *)arg, sizeof(args))) return -EINVAL;
-  f = fdget(args.fd);
-  if (!f.file) return -EBADF;
-  fops = f.file->f_op;
-  if (!fops) fops = dummy_fops;
-  fdput(f);
+  filp = fget(args.fd);
+  if (!filp) return -EBADF;
+  fops = filp->f_op;
+  if (!fops) fops = &dummy_fops;
+  fput(filp);
   if (copy_to_user((struct file_operations __user *)args.retp, fops, sizeof(*fops))) return -EINVAL;
   return 0;
 }
   if (copy_to_user((struct file_operations __user *)args.retp, fops, sizeof(*fops))) return -EINVAL;
   return 0;
 }
@@ -47,8 +47,7 @@ static int ioctl_release(struct inode *nodp, struct file *filp) {
 
 static const struct file_operations ioctl_fops = {
   .owner = THIS_MODULE,
 
 static const struct file_operations ioctl_fops = {
   .owner = THIS_MODULE,
-  .ioctl = ioctl_ioctl, /* I have no idea about locking,
-                           so just take the Big Kernel Lock implicitly. */
+  .unlocked_ioctl = ioctl_ioctl,
   .open = ioctl_open,
   .release = ioctl_release
 };
   .open = ioctl_open,
   .release = ioctl_release
 };
@@ -59,7 +58,7 @@ static struct miscdevice ioctl_miscdev = {
   .fops = &ioctl_fops
 };
 
   .fops = &ioctl_fops
 };
 
-static int __init init_ioctl() {
+static int __init init_ioctl(void) {
   int ret;
   printk(KERN_INFO "loading ioctl helper\n");
 
   int ret;
   printk(KERN_INFO "loading ioctl helper\n");
 
@@ -67,7 +66,7 @@ static int __init init_ioctl() {
   return ret;
 }
 
   return ret;
 }
 
-static void __exit cleanup_ioctl() {
+static void __exit cleanup_ioctl(void) {
   printk(KERN_INFO "unloading ioctl helper\n");
   misc_deregister(&ioctl_miscdev);
 }
   printk(KERN_INFO "unloading ioctl helper\n");
   misc_deregister(&ioctl_miscdev);
 }
diff --git a/show_ioctl.c b/show_ioctl.c
new file mode 100644 (file)
index 0000000..e090d9a
--- /dev/null
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/ioctl.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+struct fetch_fops_args {
+  int fd;
+  uint64_t retp;
+};
+
+#define MOCTEL_FETCH_FOPS _IOR('m', 1, struct fetch_fops_args)
+
+struct file_operations {
+        void *owner;
+        void *llseek;
+        void *read;
+        void *write;
+        void *aio_read;
+        void *aio_write;
+        void *readdir;
+        void *poll;
+        void *unlocked_ioctl;
+        void *compat_ioctl;
+        void *mmap;
+        void *open;
+        void *flush;
+        void *release;
+        void *fsync;
+        void *aio_fsync;
+        void *fasync;
+        void *lock;
+        void *sendpage;
+        void *get_unmapped_area;
+        void *check_flags;
+        void *flock;
+        void *splice_write;
+        void *splice_read;
+        void *setlease;
+        void *fallocate;
+};
+
+
+
+int main(int argc, char **argv) {
+  if (argc != 2) fputs("Usage: show_ioctl <device>\n", stderr), exit(1);
+
+  char *devname = argv[1];
+  int devfd = open(devname, O_RDONLY);
+  if (devfd == -1) fprintf(stderr, "Can't open %s: %m\n", devname), exit(1);
+
+  int ioctlfd = open("/dev/ioctl_info", O_RDONLY);
+  if (ioctlfd == -1) fprintf(stderr, "Can't open /dev/ioctl_info: %m\n"), exit(1);
+
+  struct file_operations fops;
+  struct fetch_fops_args ioctl_args = {
+    .fd = devfd,
+    .retp = (uint64_t)&fops
+  };
+  int ret = ioctl(ioctlfd, MOCTEL_FETCH_FOPS, &ioctl_args);
+  if (ret) fprintf(stderr, "can't perform MOCTEL_FETCH_FOPS: %m\n"), exit(1);
+
+  close(ioctlfd);
+  close(devfd);
+
+  printf("unlocked_ioctl: %llx\n", (unsigned long long)fops.unlocked_ioctl);
+
+  return 0;
+}