Это для образовательных целей, и я новичок в программировании ядра. Я пытаюсь переопределить sys_call_table [__NR_getdents] с моей пользовательской функцией. Цель моей пользовательской функции - прочитать все файлы моего текущего каталога. В man-pages говорится, что d_name - это имя файла, а d_reclen - это размер структуры. Из примера кода и поиска в Google, я понимаю, что для получения следующего имени файла мне нужно добавить d_reclen (offset) с существующей структурой obj. Продолжить цикл даст мне список всех файлов в текущем каталоге. Пожалуйста, исправьте, если понимание неверно.
Однако этого не происходит. Вот моя структура,
struct linux_dirent {
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[];
};
Вот моя пользовательская функция для замены sys_call_table [__NR_getdents]
asmlinkage int ( *orig_getdents )(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count);
// Custom function
asmlinkage int sys_getdents_new(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count) {
struct linux_dirent *retn;
// unsigned long Records;
int Records, RemainingBytes;
unsigned short length;
Records = (*orig_getdents)(fd, dirent, count);
//printk(KERN_INFO "Inside sys_getdents_new : %d", Records);
//printk(KERN_INFO "dirent lenght : %hu", dirent->d_reclen);
if (Records <= 0){
printk(KERN_INFO "Record is 0 or less");
return Records;
}
// allocating retn (with the size of Record), in kernel memory
retn = (struct linux_dirent *) kmalloc(Records, GFP_KERNEL);
// coping the content of dirent --> (to) --> rent
copy_from_user(retn, dirent, Records);
printk(KERN_INFO "retn->d_reclen %hu", retn->d_reclen);
printk(KERN_INFO "retn->d_name %s", retn->d_name);
RemainingBytes = Records;
int i=100;
// As retn->d_reclen always yields 0, RemainingBytes remains the
same causing infinite loop
// while(RemainingBytes > 0){
while(i > 0){
RemainingBytes -= retn->d_reclen;
printk(KERN_INFO "RemainingBytes %d \t File: %s " , RemainingBytes , retn->d_name );
retn = (struct linux_dirent *) ((char *)retn + retn->d_reclen);
printk(KERN_INFO "Next decrease from RemainingBytes %d " , retn->d_reclen);
i--;
}
// Copy the record back to the origional struct
//copy_to_user(dirent, retn, Records);
//kfree(retn);
return Records;
}
Вот журнал dmesg, который я получение.
[ 66.825638] RemainingBytes 80 File:
[ 66.825638] Next decrease from RemainingBytes 0
[ 66.825639] RemainingBytes 80 File:
[ 66.825640] Next decrease from RemainingBytes 0
[ 66.825640] RemainingBytes 80 File:
[ 66.825641] Next decrease from RemainingBytes 0
[ 66.825642] RemainingBytes 80 File:
[ 66.825642] Next decrease from RemainingBytes 0
[ 66.825643] RemainingBytes 80 File:
[ 66.825644] Next decrease from RemainingBytes 0
[ 66.825644] RemainingBytes 80 File:
[ 66.825645] Next decrease from RemainingBytes 0
............
[ 66.825778] RemainingBytes 80 File:
[ 66.825779] Next decrease from RemainingBytes 0
[ 66.825781] Record is 0 or less
[ 66.825820] retn->d_reclen 0
[ 66.825821] retn->d_name
[ 66.825821] RemainingBytes 80 File:
[ 66.825822] Next decrease from RemainingBytes 0
[ 66.825823] RemainingBytes 80 File:
[ 66.825823] Next decrease from RemainingBytes 0
........
Как видите, все члены linux_dirent показывают 0, что не ожидается. Поэтому внутри пока ничего не меняется. Любая идея, что я сделал не так? Пожалуйста, помогите