ioctl.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /* https://cirosantilli.com/linux-kernel-module-cheat#ioctl */
  2. #include <linux/debugfs.h>
  3. #include <linux/module.h>
  4. #include <linux/printk.h> /* printk */
  5. #include <linux/uaccess.h> /* copy_from_user, copy_to_user */
  6. #include <lkmc/ioctl.h>
  7. static struct dentry *debugfs_file;
  8. static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp)
  9. {
  10. void __user *arg_user;
  11. union {
  12. int i;
  13. lkmc_ioctl_struct s;
  14. } arg_kernel;
  15. arg_user = (void __user *)argp;
  16. pr_info("cmd = %x\n", cmd);
  17. switch (cmd) {
  18. case LKMC_IOCTL_INC:
  19. if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) {
  20. return -EFAULT;
  21. }
  22. pr_info("0 arg = %d\n", arg_kernel.i);
  23. arg_kernel.i += 1;
  24. if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) {
  25. return -EFAULT;
  26. }
  27. break;
  28. case LKMC_IOCTL_INC_DEC:
  29. if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) {
  30. return -EFAULT;
  31. }
  32. pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j);
  33. arg_kernel.s.i += 1;
  34. arg_kernel.s.j -= 1;
  35. if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) {
  36. return -EFAULT;
  37. }
  38. break;
  39. default:
  40. return -EINVAL;
  41. break;
  42. }
  43. return 0;
  44. }
  45. static const struct file_operations fops = {
  46. .owner = THIS_MODULE,
  47. .unlocked_ioctl = unlocked_ioctl
  48. };
  49. static int myinit(void)
  50. {
  51. /* ioctl permissions are not automatically restricted by rwx as for read / write,
  52. * but we could of course implement that ourselves:
  53. * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */
  54. debugfs_file = debugfs_create_file("lkmc_ioctl", 0, NULL, NULL, &fops);
  55. return 0;
  56. }
  57. static void myexit(void)
  58. {
  59. debugfs_remove(debugfs_file);
  60. }
  61. module_init(myinit)
  62. module_exit(myexit)
  63. MODULE_LICENSE("GPL");