X-Git-Url: http://git.thejh.net/?p=moctel.git;a=blobdiff_plain;f=moctel_mod.c;h=1273ff31512a3cfb54c475daad6f7a1edcf7f265;hp=47d63f83c5bcf24006e2a057d717d665f925735a;hb=c5475c04c00783d8b55ce5d5b4a3dc55eb16dac6;hpb=b1d5f41202848183d1b6e291afa448c631994d6c diff --git a/moctel_mod.c b/moctel_mod.c index 47d63f8..1273ff3 100644 --- a/moctel_mod.c +++ b/moctel_mod.c @@ -1,3 +1,7 @@ +// Copyright (C) 2013 Jann Horn +// This file is licensed under the GNU GPL v2 (see +// the LICENSE file). + #undef __KERNEL__ #define __KERNEL__ #undef MODULE @@ -11,6 +15,8 @@ #include #include #include +#include +#include struct fetch_fops_args { int fd; @@ -23,21 +29,29 @@ static int ioctl_open(struct inode *nodp, struct file *filp) { return 0; } -static const struct file_operations dummy_fops = {}; - static long ioctl_ioctl(struct file *filp_, unsigned int cmd, unsigned long arg) { struct fetch_fops_args args; struct file *filp; - const struct file_operations *fops; + void *ioctl_method = NULL; + char ioctl_method_name[KSYM_NAME_LEN]; + int (*lookup_symbol_name_)(unsigned long addr, char *symname); + + lookup_symbol_name_ = (void*)kallsyms_lookup_name("lookup_symbol_name"); if (cmd != MOCTEL_FETCH_FOPS) return -EINVAL; + memset(ioctl_method_name, 0, sizeof(ioctl_method_name)); if (copy_from_user(&args, (struct fetch_fops_args __user *)arg, sizeof(args))) return -EINVAL; filp = fget(args.fd); if (!filp) return -EBADF; - fops = filp->f_op; - if (!fops) fops = &dummy_fops; + if (filp->f_op) ioctl_method = filp->f_op->unlocked_ioctl; + lookup_symbol_name_((unsigned long)ioctl_method, ioctl_method_name); + if (strcmp(ioctl_method_name, "block_ioctl") == 0) { + struct block_device *bdev = I_BDEV(filp->f_mapping->host); + ioctl_method = bdev->bd_disk->fops->ioctl; + lookup_symbol_name_((unsigned long)ioctl_method, ioctl_method_name); + } fput(filp); - if (copy_to_user((struct file_operations __user *)args.retp, fops, sizeof(*fops))) return -EINVAL; + if (copy_to_user((struct file_operations __user *)args.retp, ioctl_method_name, KSYM_NAME_LEN)) return -EINVAL; return 0; } @@ -73,3 +87,5 @@ static void __exit cleanup_ioctl(void) { module_init(init_ioctl); module_exit(cleanup_ioctl); + +MODULE_LICENSE("GPL v2");