2015-03-18 2 views
0

Я получаю сбой в результате звонка kmap, и я не знаю, почему. Я надеюсь, что кто-то с большим количеством знаний о ядре, чем я могу помочь с этим. Вот код:Чтение содержимого страницы пользовательского пространства из ядра

pgd_t *pgd = pgd_offset(vma->vm_mm, userspace_addr); 
    pud_t *pud = pud_offset(pgd, userspace_addr); 
    pmd_t *pmd = pmd_offset(pud, userspace_addr); 
    pte_t *pte = pte_offset_map(pmd, userspace_addr); 

    if (pte_present_user(*pte)) { 
      void *p = NULL; 
      struct page *page = pte_page(*pte); 

      get_page(page); 
      p = kmap(page); /* CRASH HERE??? */ 

      /* Read from 'p' */ 

      kunmap(p); 
      put_page(page); 
    } 

Я изолирован, что вызов kmap является виновником, так как без него код работает нормально. Насколько я могу судить, все указатели действительны.

Я уверен, если pte_offset_map должен быть использован в сочетании с kmap ...

Код выше запускается с mm->mmap_sem и vma->vm_mm->page_table_lock запертой и на kthread в контексте ядра.

+0

Вы выполнили 'access_ok()' на 'userspage_addr' –

+0

@Miline: я добавил чек, и у меня есть доступ к странице. Я также попытался заменить вызов 'kmap()' 'page_address()', но NULL был возвращен. Я не уверен, что это значит. – MarkP

+0

Что произойдет, если вы удалите kmap()? Я думаю, что pte_offset_map() делает kmap_atomic() внутренне –

ответ

0

Я думаю, что решил. Основная проблема в моем коде заключалась в том, что я передавал указатель, возвращенный с kmap в kunmap. Я должен был перейти в указатель страницы.

Еще одно изменение заключается в использовании pte_offset_kernel вместо pte_offset_map.