From: Jann Horn Date: Sat, 18 May 2013 23:41:57 +0000 (+0200) Subject: it works! :) X-Git-Url: http://git.thejh.net/?p=moctel.git;a=commitdiff_plain;h=b1d5f41202848183d1b6e291afa448c631994d6c;hp=9ca13033981db455c571e6f54f4ac24938afb94a;ds=sidebyside it works! :) --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f3ee05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +show_ioctl +moctel_mod.ko +moctel_mod.mod.* +.tmp_versions +*.cmd +modules.order +*.o +Module.symvers diff --git a/Makefile b/Makefile index ac7b8da..5516404 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,12 @@ 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 + +show_ioctl: + gcc -o show_ioctl show_ioctl.c -std=gnu99 clean: $(MAKE) -C $(KDIR) M=$(PWD) clean diff --git a/moctel_mod.c b/moctel_mod.c index bb0652e..47d63f8 100644 --- a/moctel_mod.c +++ b/moctel_mod.c @@ -25,18 +25,18 @@ static int ioctl_open(struct inode *nodp, struct file *filp) { 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 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; - 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; } @@ -47,8 +47,7 @@ static int ioctl_release(struct inode *nodp, struct file *filp) { 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 }; @@ -59,7 +58,7 @@ static struct miscdevice ioctl_miscdev = { .fops = &ioctl_fops }; -static int __init init_ioctl() { +static int __init init_ioctl(void) { int ret; printk(KERN_INFO "loading ioctl helper\n"); @@ -67,7 +66,7 @@ static int __init init_ioctl() { return ret; } -static void __exit cleanup_ioctl() { +static void __exit cleanup_ioctl(void) { 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 index 0000000..e090d9a --- /dev/null +++ b/show_ioctl.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include + +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 \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; +}