Почему члены struct linux_dirent (d_name, d_reclen, ..) всегда получают 0? - PullRequest
0 голосов
/ 03 апреля 2020

Это для образовательных целей, и я новичок в программировании ядра. Я пытаюсь переопределить 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, что не ожидается. Поэтому внутри пока ничего не меняется. Любая идея, что я сделал не так? Пожалуйста, помогите

...