diff --git a/README.md b/README.md index a8eb047..15506e1 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,56 @@ echo "bonjour12" > /dev/eudyptula * [Linux Kernel Labs - Character device drivers](https://linux-kernel-labs.github.io/refs/heads/master/labs/device_drivers.html#read-and-write) * [Nihall - Misc character devices](https://nihaal.me/post/misc_char_devices/) +## Tache 8 + +L'ajout d'une nouvelle string dans le fichier ne supprime l'entièreté du +contenu du fichier. J'ai testé les sémaphores avec des `msleep` +(``) rajouté dans le code. Il est possible de tester en +décommentant le premier `define`. + +```bash +ls -l /sys/kernel/debug/eudyptula/ +# total 0 +# -rw-rw-r-- 1 root root 0 Jan 9 22:46 foo +# -rw-rw-rw- 1 root root 0 Jan 9 22:44 id +# -r--r--r-- 1 root root 0 Jan 9 22:45 jiffies +echo pouet > /sys/kernel/debug/eudyptula/foo +cat /sys/kernel/debug/eudyptula/foo +# pouet +echo coucou ! > /sys/kernel/debug/eudyptula/foo +cat /sys/kernel/debug/eudyptula/foo +# coucou ! +cat /sys/kernel/debug/eudyptula/id +# pouetpouet +echo congruent > /sys/kernel/debug/eudyptula/id +echo $? +# 0 +echo pouet > /sys/kernel/debug/eudyptula/id +# bash: echo: write error: Invalid argument +echo $? +# 1 +echo pouet > /sys/kernel/debug/eudyptula/jiffies +# bash: echo: write error: Permission denied +cat /sys/kernel/debug/eudyptula/jiffies +# 4345895105 +cat /sys/kernel/debug/eudyptula/jiffies +# 4345895338 +echo pouet > /sys/kernel/debug/eudyptula/foo & +cat /sys/kernel/debug/eudyptula/foo +# cat: /sys/kernel/debug/eudyptula/foo: Invalid argument +cat /sys/kernel/debug/eudyptula/foo & +cat /sys/kernel/debug/eudyptula/foo & +echo pouet > /sys/kernel/debug/eudyptula/foo +# bash: echo: write error: Invalid argument +rmmod hello +ls -l /sys/kernel/debug/eudyptula/ +# ls: cannot access '/sys/kernel/debug/eudyptula/': No such file or directory +``` + + * [DebugFS (Documentation kernel)](https://docs.kernel.org/filesystems/debugfs.html) + * [Chapitre 3, Linux Device Drivers, 3rd Edition](https://lwn.net/Kernel/LDD3/) + * [Jiffies, Linux Kernel Development 2nd Edition](https://litux.nl/mirror/kerneldevelopment/0672327201/ch10lev1sec3.html) + ## Informations diverses Je liste dans cette section quelques informations que j'ai pu découvrir en diff --git a/task_08/Makefile b/task_08/Makefile new file mode 100644 index 0000000..d73cca6 --- /dev/null +++ b/task_08/Makefile @@ -0,0 +1,9 @@ +obj-m += debugfs.o + +PWD := $(CURDIR) + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/task_08/debugfs.c b/task_08/debugfs.c new file mode 100644 index 0000000..6fff8f0 --- /dev/null +++ b/task_08/debugfs.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 + +//#define DEBUG 1 + +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +#include +#endif + +#define BUFFER_LENGTH 10 + +static struct dentry *folder; +static struct dentry *id_file; +static struct dentry *foo_file; + +static char *id_msg; +static char *foo_msg; +static struct rw_semaphore foo_sem; + +static ssize_t id_read(struct file *, char __user *buffer, size_t length, loff_t *offset) +{ + int bytes = 0; + const char *msg_tmp = id_msg; + + /* + * TODO + if (!*(msg_tmp + *offset)) { + *offset = 0; + return 0; + } + */ + + msg_tmp += *offset; + + while (*msg_tmp && bytes < length) { + put_user(*(msg_tmp), (buffer + bytes)); + bytes++; + msg_tmp++; + } + + *offset += bytes; + return bytes; +} + +static ssize_t id_write(struct file *, const char __user *buffer, + size_t size, loff_t *) +{ + int ret; + char *tmp_buffer; + + if (size == 0) + return 0; + + tmp_buffer = kzalloc(BUFFER_LENGTH, GFP_KERNEL); + + if (copy_from_user(tmp_buffer, buffer, BUFFER_LENGTH)) { + kfree(tmp_buffer); + return -EINVAL; + } + + *(tmp_buffer + BUFFER_LENGTH - 1) = '\0'; + pr_info("Test %s-\n", tmp_buffer); + + if (!strcmp(tmp_buffer, "congruent")) + ret = BUFFER_LENGTH; + else + ret = -EINVAL; + + kfree(tmp_buffer); + return ret; +} + +static const struct file_operations id_fops = { + .owner = THIS_MODULE, + .read = id_read, + .write = id_write, +}; + +static ssize_t foo_read(struct file *, char __user *buffer, size_t count, loff_t *offset) +{ + int bytes = -EINVAL; + int tmp_len = strlen(foo_msg); + + if (*offset > tmp_len) bytes = -EFAULT; + else if (down_read_trylock(&foo_sem)) + { + char *tmp_str = foo_msg + *offset; + tmp_len = strlen(tmp_str); + + bytes = tmp_len > count ? count : tmp_len; + if (copy_to_user(buffer, tmp_str, bytes)) bytes = -EFAULT; + else *offset += bytes; +#ifdef DEBUG + msleep(5000); +#endif + up_read(&foo_sem); + } + + return bytes; +} + +static ssize_t foo_write(struct file *, const char __user *buffer, + size_t count, loff_t * offset) +{ + int bytes = -EINVAL; + + if ((*offset + count) > PAGE_SIZE) bytes = -EFAULT; + else if (down_write_trylock(&foo_sem)) + { + bytes = count; + if (copy_from_user(foo_msg, buffer, bytes)) bytes = -EINVAL; +#ifdef DEBUG + msleep(5000); +#endif + up_write(&foo_sem); + } + + return bytes; +} + +static const struct file_operations foo_fops = { + .owner = THIS_MODULE, + .read = foo_read, + .write = foo_write, +}; + +static int __init my_init(void) +{ + init_rwsem(&foo_sem); + id_msg = kmalloc(12, GFP_KERNEL); + foo_msg = kmalloc(PAGE_SIZE, GFP_KERNEL); + strcpy(id_msg, "pouetpouet\n"); + pr_info("Coucou le gens !!!!\n"); + + folder = debugfs_create_dir("eudyptula", NULL); + id_file = debugfs_create_file("id", 0666, folder, NULL, &id_fops); + debugfs_create_u64("jiffies", 0444, folder, &jiffies_64); + foo_file = debugfs_create_file("foo", 0664, folder, NULL, &foo_fops); + + return 0; +} + +static void __exit my_exit(void) +{ + debugfs_remove_recursive(folder); + kfree(id_msg); + kfree(foo_msg); + pr_info("Tschuss !!!\n"); +} + +module_init(my_init); +module_exit(my_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("rick "); +MODULE_DESCRIPTION("Module pour tester le debugfs.");