Ошибка "Bad Address" при выполнении copy_to_user из модуля ядра Linux - PullRequest
0 голосов
/ 05 мая 2018

Я реализую модуль ядра (версия 2.6.32), который может записывать в / proc и позволяет записывать и читать из / в пользовательское пространство и пространство ядра. Мой код записи в пространство ядра работает отлично, но при попытке copy_to_user я получаю сообщение о том, что у него «неправильный адрес».

Я использую echo "test" > procmodule (имя моего модуля) и cat procmodule для извлечения строки из памяти модуля. Результат второй команды

cat: procmodule: неправильный адрес

Ниже приведен соответствующий код:

int read_info( char *page , char **start, off_t off, int count, int *eof, void *data) {    
    if(copy_to_user(page, info, count)){
     return -EFAULT;
    }
    return count;
}

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

Что я пробовал:

  • Распечатывая строку "info", она печатает то, что я хочу видеть, поэтому массив не является проблемой
  • Печать "страницы", указатель существует
  • При изменении прав доступа модуля в create_proc_entry по-прежнему возникает ошибка
  • Возвращение 0, размера самого массива и результата copy_to_user (который был размером буфера, который был записан, должен совпадать с count) в конце функции, та же ошибка. Если необходимо, copy_to_user возвращает 3072

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

1 Ответ

0 голосов
/ 06 мая 2018

Первый аргумент функции .read_proc (типа read_proc_t) на самом деле адрес в ядре . Вы можете написать по этому адресу напрямую, и не должны использовать copy_to_user для этого.


Вы, наверное, путаете свою функцию с функцией .read в структуре file_operations. Эта функция имеет подпись

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

и его второй аргумент фактически является указателем на пространство пользователя (таким образом, он имеет спецификатор __user), для которого следует использовать copy_to_user.

Обратите внимание, что первый аргумент вашей функции не имеет спецификатора __user:

typedef int (read_proc_t)(char *page, char **start, off_t off,
          int count, int *eof, void *data);
...