ioctl.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. Input: an integer (with some annoying restrictions) and a pointer
  3. Output:
  4. - positive integer return value, which for sanity should only be used with negative values for success
  5. - the input pointer data may be overwritten to contain output
  6. Feels like an archaic API... so many weird restrictions and types for something that could be so simple!
  7. Documentation/ioctl/ioctl-number.txt has some info:
  8. _IO an ioctl with no parameters
  9. _IOW an ioctl with write parameters (copy_from_user)
  10. _IOR an ioctl with read parameters (copy_to_user)
  11. _IOWR an ioctl with both write and read parameters.
  12. - https://stackoverflow.com/questions/2264384/how-do-i-use-ioctl-to-manipulate-my-kernel-module/44613896#44613896
  13. - https://askubuntu.com/questions/54239/problem-with-ioctl-in-a-simple-kernel-module/926675#926675
  14. */
  15. #include <linux/debugfs.h>
  16. #include <linux/module.h>
  17. #include <linux/printk.h> /* printk */
  18. #include <linux/uaccess.h> /* copy_from_user, copy_to_user */
  19. #include "ioctl.h"
  20. static struct dentry *debugfs_file;
  21. static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp)
  22. {
  23. void __user *arg_user;
  24. union {
  25. int i;
  26. lkmc_ioctl_struct s;
  27. } arg_kernel;
  28. arg_user = (void __user *)argp;
  29. pr_info("cmd = %x\n", cmd);
  30. switch (cmd) {
  31. case LKMC_IOCTL_INC:
  32. if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) {
  33. return -EFAULT;
  34. }
  35. pr_info("0 arg = %d\n", arg_kernel.i);
  36. arg_kernel.i += 1;
  37. if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) {
  38. return -EFAULT;
  39. }
  40. break;
  41. case LKMC_IOCTL_INC_DEC:
  42. if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) {
  43. return -EFAULT;
  44. }
  45. pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j);
  46. arg_kernel.s.i += 1;
  47. arg_kernel.s.j -= 1;
  48. if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) {
  49. return -EFAULT;
  50. }
  51. break;
  52. default:
  53. return -EINVAL;
  54. break;
  55. }
  56. return 0;
  57. }
  58. static const struct file_operations fops = {
  59. .owner = THIS_MODULE,
  60. .unlocked_ioctl = unlocked_ioctl
  61. };
  62. static int myinit(void)
  63. {
  64. /* ioctl permissions are not automatically restricted by rwx as for read / write,
  65. * but we could of course implement that ourselves:
  66. * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */
  67. debugfs_file = debugfs_create_file("lkmc_ioctl", 0, NULL, NULL, &fops);
  68. return 0;
  69. }
  70. static void myexit(void)
  71. {
  72. debugfs_remove(debugfs_file);
  73. }
  74. module_init(myinit)
  75. module_exit(myexit)
  76. MODULE_LICENSE("GPL");