From 0657191cf04805caa3c7a0325239d119b53f41a4 Mon Sep 17 00:00:00 2001 From: Imbus Date: Tue, 24 Feb 2026 13:49:54 +0100 Subject: [PATCH] Ioctl --- ioctl_chardev/Makefile | 11 +++++++ ioctl_chardev/README.txt | 7 +++++ ioctl_chardev/my-ioctl.c | 67 ++++++++++++++++++++++++++++++++++++++++ ioctl_chardev/my-ioctl.h | 18 +++++++++++ ioctl_chardev/test.c | 40 ++++++++++++++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 ioctl_chardev/Makefile create mode 100644 ioctl_chardev/README.txt create mode 100644 ioctl_chardev/my-ioctl.c create mode 100644 ioctl_chardev/my-ioctl.h create mode 100644 ioctl_chardev/test.c diff --git a/ioctl_chardev/Makefile b/ioctl_chardev/Makefile new file mode 100644 index 0000000..78be925 --- /dev/null +++ b/ioctl_chardev/Makefile @@ -0,0 +1,11 @@ +obj-m = my-ioctl.o + +all: test.elf + make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean + rm test.elf + +test.elf: test.c + $(CC) test.c -o test.elf diff --git a/ioctl_chardev/README.txt b/ioctl_chardev/README.txt new file mode 100644 index 0000000..2945fc1 --- /dev/null +++ b/ioctl_chardev/README.txt @@ -0,0 +1,7 @@ +sudo rmmod my_ioctl +sudo insmod my_ioctl.ko + +The device node is created automatically on load. + +Otherwise: + sudo mknod /dev/hello c diff --git a/ioctl_chardev/my-ioctl.c b/ioctl_chardev/my-ioctl.c new file mode 100644 index 0000000..78b2db0 --- /dev/null +++ b/ioctl_chardev/my-ioctl.c @@ -0,0 +1,67 @@ +#include +#include "my-ioctl.h" + +MODULE_DESCRIPTION("Chardev Ioctl kernel module."); +MODULE_VERSION("0.0.1"); +MODULE_AUTHOR("Imbus"); +MODULE_LICENSE("GPL"); + +#define DEVICE_NAME "hello_ioctl" + +static int major; /* Dynamically assigned */ +static struct class *cls; + +static long my_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); + +/* See: https://elixir.bootlin.com/linux/v6.14.5/source/include/linux/fs.h#L2131 */ +static struct file_operations fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = my_ioctl, +}; + +static long my_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + pr_info("Ioctl called by %s...\n", current->comm); + + switch (cmd) { + case MY_IOCTL_FILL: + pr_info("Ioctl FILL by %s...\n", current->comm); + break; + case MY_IOCTL_WIPE: + pr_info("Ioctl WIPE by %s...\n", current->comm); + break; + default: + return -ENOTTY; // Invalid command + } + return 0; +} + +static int __init demo_mod_init(void) +{ + major = register_chrdev(0, DEVICE_NAME, &fops); + if (major < 0) { + pr_info(DEVICE_NAME " - Error registering chrdev\n"); + return major; + } + + pr_info(DEVICE_NAME " was assigned major number %d.\n", major); + + cls = class_create(DEVICE_NAME); + device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); + + pr_info(DEVICE_NAME " created on /dev/%s\n", DEVICE_NAME); + + pr_info(DEVICE_NAME " major nbr %d loaded successfully...\n", major); + return 0; +} + +static void __exit demo_mod_exit(void) +{ + device_destroy(cls, MKDEV(major, 0)); + class_destroy(cls); + unregister_chrdev(major, DEVICE_NAME); + pr_info(DEVICE_NAME " unloaded successfully...\n"); +} + +module_init(demo_mod_init); +module_exit(demo_mod_exit); diff --git a/ioctl_chardev/my-ioctl.h b/ioctl_chardev/my-ioctl.h new file mode 100644 index 0000000..56b61a4 --- /dev/null +++ b/ioctl_chardev/my-ioctl.h @@ -0,0 +1,18 @@ +#ifndef MY_IOCTL_H +#define MY_IOCTL_H +#include + +/* + * Crucial point here, the kernel defines a set of macros for defining IOCTL numbers: + * _IO - No command + * _IOR - Read command + * _IOW - Write command + * _IORW - RW command + * _IOC - Basis of the others + * These macros encode the data type passed to the ioctl. + */ + +#define MY_IOCTL_WIPE _IO('k', 0x01) +#define MY_IOCTL_FILL _IO('k', 0x02) /* Name is a placeholder, fills nothing */ + +#endif // MY-IOCTL_H diff --git a/ioctl_chardev/test.c b/ioctl_chardev/test.c new file mode 100644 index 0000000..e379cd1 --- /dev/null +++ b/ioctl_chardev/test.c @@ -0,0 +1,40 @@ +#include +// #include +#include +#include +#include +#include +#include "my-ioctl.h" + +int main(int argc, char **argv) +{ + int fd; + + if (argc < 2) { + printf("I need the file to open as an argument!\n"); + return 0; + } + + fd = open(argv[1], O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + + if (ioctl(fd, MY_IOCTL_FILL)) { + perror("ioctl"); + close(fd); + return 1; + } + + if (ioctl(fd, MY_IOCTL_WIPE)) { + perror("ioctl"); + close(fd); + return 1; + } + + printf("ioctl successful\n"); + + close(fd); + return 0; +}