I had to get some data from a user process within a kernel module. That process wasn't the "current" so the process pgd was not the same as the current pgd (for this reason I couldn't use copy_from_user function).
I had been looking for some straight method (or function) to do it, but I could not find any. I finally did it translating the address throw the corresponding page directories and page tables, using the following code:
"from" is a linear address in user space of a process using pgd (task->mm->pgd).
if (!pgd_none(*pgd)) {
pud = pud_offset(pgd, (unsigned long) from);
if (!pud_none(*pud)) {
pmd = pmd_offset(pud, (unsigned long) from);
if (!pmd_none(*pmd)) {
ptep = pte_offset_map(pmd, (unsigned long) from);
pte = *ptep;
if (pte_present(pte)) {
page = pte_page(pte);
}
pte_unmap(ptep);
}
}
}
pud = pud_offset(pgd, (unsigned long) from);
if (!pud_none(*pud)) {
pmd = pmd_offset(pud, (unsigned long) from);
if (!pmd_none(*pmd)) {
ptep = pte_offset_map(pmd, (unsigned long) from);
pte = *ptep;
if (pte_present(pte)) {
page = pte_page(pte);
}
pte_unmap(ptep);
}
}
}
Does somebody know if there is some kernel function that do this ? Or some copy_from_user function that allows to specify a different pgd (or a different task struct)?
Thanks in advance.
Best Regards.