get_user_page, get_user_pages_fast

get_user_page, get_user_pages_fast用於獲取用戶buffer所mapped的頁。

/**                             
 * get_user_pages_fast() - pin user pages in memory
 * @start:      starting user address
 * @nr_pages:   number of pages from start to pin
 * @write:      whether pages will be written to
 * @pages:      array that receives pointers to the pages pinned.
 *              Should be at least nr_pages long.
 *                      
 * Attempt to pin user pages in memory without taking mm->mmap_sem. <==不需要獲取鎖, get_user_pages_fast調用這個函數進行獲取當前進程的頁,這個函數不鎖mm的
 * If not successful, it will fall back to taking the lock and
 * calling get_user_pages().
 *
 * Returns number of pages pinned. This may be fewer than the number
 * requested. If nr_pages is 0 or negative, returns 0. If no pages
 * were pinned, returns -errno.
 */                     
int get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages)

Example:

1,get_user_pages_fast

/* TODO: This is really inefficient.  We need something like get_user()
 * (instruction directly accesses the data, with an exception table entry
 * returning -EFAULT). See Documentation/x86/exception-tables.txt.
 */
static int set_bit_to_user(int nr, void __user *addr)
{
        unsigned long log = (unsigned long)addr;
        struct page *page;
        void *base;
        int bit = nr + (log % PAGE_SIZE) * 8;
        int r;

        r = get_user_pages_fast(log, 1, 1, &page);
        if (r < 0)
                return r;
        BUG_ON(r != 1);
        base = kmap_atomic(page);
        set_bit(bit, base);
        kunmap_atomic(base);
        set_page_dirty_lock(page);
        put_page(page);
        return 0;        
}

2,get_user_pages

        down_read(&current->mm->mmap_sem);  <==需要獲取鎖
        res = get_user_pages(current, current->mm,
                (unsigned long)buf,
                1,
                1,              
                0,
                &page,
                NULL);
        if (res) {
                printk(KERN_INFO "Got mmaped.\n");
                myaddr = kmap(page);
                printk(KERN_INFO "%s\n", myaddr);
                strcpy(myaddr, "Mohan");
                page_cache_release(page);
        }
        up_read(&current->mm->mmap_sem);

 

1,get_user_pages函數詳解

https://liujunming.top/2017/07/03/get-user-pages%E5%87%BD%E6%95%B0%E8%AF%A6%E8%A7%A3/

2,頁面的引用計數和get_user_pages

https://blog.csdn.net/iteye_5014/article/details/81824739

3,Linux Kernel get_user_pages() 源碼分析

https://v1ckydxp.github.io/2020/04/22/2020-04-22-CVE-2016-5195%20%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章