Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C LKM linux_-dirent实现_C_Linux_Module_Kernel - Fatal编程技术网

C LKM linux_-dirent实现

C LKM linux_-dirent实现,c,linux,module,kernel,C,Linux,Module,Kernel,作为一项安全性研究,我试图实现一个包装系统调用。根据getdents文档,您必须实现自己的linux目录结构。这一切似乎都起作用了,但我无法正确读取linux目录名称 linux驱动程序的实现: struct mylkm_linux_dirent { u64 d_ino; s64 d_off; unsigned short d_reclen; char d_name[]; }; 已包装的getden

作为一项安全性研究,我试图实现一个包装系统调用。根据getdents文档,您必须实现自己的linux目录结构。这一切似乎都起作用了,但我无法正确读取linux目录名称

linux驱动程序的实现:

struct mylkm_linux_dirent {
    u64            d_ino;
    s64            d_off;
    unsigned short d_reclen;
    char           d_name[];
};
已包装的getdents调用:

/*
This method will call the original and then sift through results.
Method will remove results that contain the specified keyword.
*/
asmlinkage long mylkm_getdents(unsigned int fd, struct mylkm_linux_dirent * dirp, unsigned int count)
{
    unsigned int size = 0;
    unsigned int bpos = 0;
    struct mylkm_linux_dirent* dir1 = NULL;
    char * buffer_ptr = NULL;
    char hide[] = "mylkm";

    printk("mylkm: getdents() called - redirecting to original sys call.\n");
    size = (*k_getdents)(fd, dirp, count);
    printk("mylkm: bytes value returned by original getdents() call: %ld\n", size);
    printk("mylkm: count value passed into original getdents() call: %i\n", count);
    printk("mylkm: dirp pointer value: %p\n", dirp);

    for (bpos = 0; bpos<size;)
    {
        buffer_ptr = (char*)(&dirp + bpos);
        dir1 = (struct mylkm_linux_dirent*)buffer_ptr;
        printk("mylkm: record length: %d\n", dir1->d_reclen);
        printk("mylkm: record name: %s\n", dir1->d_name);
        printk("mylkm: offset to next dirent: %lld\n", (long long)dir1->d_off);

        bpos += dir1->d_reclen;
    }

    printk("mylkm: Completed mylkm_getdents() call\n");
    return 0;
}
我已经尝试将dir1->d_名称显式转换为char指针。将char指针传入原始调用时崩溃。如何获得正确的列表?

解决方案是:

使用适当的指针算法获取dirp数组的元素。例如

buffer_ptr = ((char*)dirp) + bpos;
dir1 = (struct mylkm_linux_dirent*)buffer_ptr;
通过“从用户复制”功能访问阵列元素,而不是直接访问。例如

u64 reclen; # Record length will be stored here
get_user(&reclen, &dir1->d_reclen); # TODO: check possible errors
printk("mylkm: record length: %d\n", reclen);

# Allocate a structure in the kernel
struct mylkm_linux_dirent* dir1_kernel = kmalloc(reclen, GFP_KERNEL); # TODO: check possible errors
# and copy user-space structure into it.
copy_from_user(dir1_kernel, dir1, reclen); # TODO: check possible errors

# Use dir1_kernel instead of dir
printk("mylkm: record name: %s\n", dir1_kernel->d_name);

# Free kernel structure at the end of the loop
kfree(dir1_kernel);

缓冲区\u ptr=char*&dirp+bpos;-这是否曾经编译过,dirp是指向结构的指针,因此结构中添加了一个数字?在右边,您可能需要char*dirp+bpos,它首先将指针转换为指向char的指针,然后用它进行算术运算。并检查它是否与系统调用的dirp参数一致,即在第一次迭代时dir1应等于dirp;在下一次迭代中,dir1应该等于它以前的值加上以前的记录长度。@Tsyvarev我同意。。。该程序因char*dirp+BPO而崩溃。与尝试将指针强制转换为结构mylkm_linux_dirent*@Tsyvarev时一样,我将检查这一点。我还将手动增加指针位置,并尝试获取reclen和name变量,对于u long为4字节,对于u short为2字节。reclen=dirp+bpos+8;name=dirp+bpos+10;printkmylkm:记录长度:%d\n,重新打开;printkmylkm:记录名称:%s\n,名称;char*name变量的打印输出崩溃。雷肯成功了。
u64 reclen; # Record length will be stored here
get_user(&reclen, &dir1->d_reclen); # TODO: check possible errors
printk("mylkm: record length: %d\n", reclen);

# Allocate a structure in the kernel
struct mylkm_linux_dirent* dir1_kernel = kmalloc(reclen, GFP_KERNEL); # TODO: check possible errors
# and copy user-space structure into it.
copy_from_user(dir1_kernel, dir1, reclen); # TODO: check possible errors

# Use dir1_kernel instead of dir
printk("mylkm: record name: %s\n", dir1_kernel->d_name);

# Free kernel structure at the end of the loop
kfree(dir1_kernel);