Страница ядра Linux C мешает работе с предыдущей переменной

Я хочу зацепить read в ядре Linux, чтобы показать, какой процесс читает файл в /home/xytao/safe каталог.

// get absolute file path from file struct
char *get_filename(struct file *file)
{
    char *buf = (char *)__get_free_page(GFP_KERNEL);
    if (!buf)
    {
        return NULL;
    }
    char *filename = dentry_path_raw(file->f_path.dentry, buf, PAGE_SIZE - 1);
    if (IS_ERR(filename))
    {
        free_page((unsigned long)buf);
        return NULL;
    }
    free_page((unsigned long)buf);
    return filename;
}

asmlinkage ssize_t fake_read(int __fd, void *__buf, size_t __nbytes)
{
    char *pathname;
    struct file *file;
    struct path *path;
    struct files_struct *files = current->files;
    spin_lock(&files->file_lock);
    file = fcheck_files(files, __fd);
    if (!file)
    {
        spin_unlock(&files->file_lock);
        return -ENOENT;
    }
    spin_unlock(&files->file_lock);
    ssize_t out = real_read(__fd, __buf, __nbytes);
    pathname=get_filename(file);
    if (!strncmp(pathname, "/home/xytao/safe", 15))
    {   fm_alert("pathname_before:%s\n", pathname);
        struct file *process_file = get_task_exe_file(current);
        fm_alert("process_name:%s\n", get_filename(process_file));
        fm_alert("pathname_after:%s\n:", pathname);    
    }
    return out;
}

Но похоже pathname был изменен после получения имени процесса, и pathname был скомпрометирован get_filename(process_file),

Например, после того, как я открываю /home/xytao/safe/test Я получаю следующий вывод:

[ 1181.179485] fsmonko.fake_read: pathname_before:/home/xytao/safe/test
[ 1181.179488] fsmonko.fake_read: process_name:/usr/bin/gedit
[ 1181.179490] fsmonko.fake_read: pathname_after:/home/x/usr/bin/gedit
           :
[ 1181.181590] fsmonko.fake_read: pathname_before:/home/xytao/safe/test
[ 1181.181594] fsmonko.fake_read: process_name:/usr/bin/gedit
[ 1181.181595] fsmonko.fake_read: pathname_after:/home/x/usr/bin/gedit
           :
[ 1181.190503] fsmonko.fake_read: pathname_before:/home/xytao/safe/test
[ 1181.190509] fsmonko.fake_read: process_name:/usr/bin/gedit
[ 1181.190511] fsmonko.fake_read: pathname_after:/home/x/usr/bin/gedit
           :
[ 1197.523906] fsmonko.fake_read: pathname_before:/home/xytao/safe/test
[ 1197.523915] fsmonko.fake_read: process_name:/usr/bin/nautilus

Как это исправить?

1 ответ

dentry_path_raw не выделяет имя файла (строку) для вас; он копирует его в предоставленный вами буфер памяти. Когда вы освобождаете эту страницу, имя файла становится висячей ссылкой. Было бы лучше, если бы вы взяли на себя ошибку страницы, ссылаясь на нее, но была бы цена за производительность, если free_page немедленно обновил сопоставления страниц.

имя файла будет указывать где-то посередине буфера, который вы предоставляете, так что вы можете освободить его в вызывающей стороне с помощью:

free_page((uintptr_t)filename & PAGE_MASK);
Другие вопросы по тегам