#include <linux/ioctl.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
+#include <linux/kallsyms.h>
+#include <linux/blkdev.h>
struct fetch_fops_args {
int fd;
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;
}
module_init(init_ioctl);
module_exit(cleanup_ioctl);
+
+MODULE_LICENSE("GPL v2");
#include <fcntl.h>
#include <sys/ioctl.h>
+#define KSYM_NAME_LEN 128
+
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);
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;
+ char resbuf[KSYM_NAME_LEN];
struct fetch_fops_args ioctl_args = {
.fd = devfd,
- .retp = (uint64_t)&fops
+ .retp = (uint64_t)resbuf
};
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);
+ printf("%s\n", resbuf);
return 0;
}