2013-02-20 97 views
10

我總是被告知(在書籍和教程中),當將數據從內核空間複製到用戶空間時,我們應該使用copy_to_user()並使用memcpy()會導致系統出現問題。最近我錯誤地使用了memcpy(),它在任何問題都很好地工作。 這是爲什麼我們應該用它代替的memcpy()copy_to_usercopy_to_user vs memcpy

我的測試代碼(內核模塊)是這樣的:

static ssize_t test_read(struct file *file, char __user * buf, 
      size_t len, loff_t * offset) 
{ 
    char ani[100]; 

    if (!*offset) { 
     memset(ani, 'A', 100); 
     if (memcpy(buf, ani, 100)) 
      return -EFAULT; 
     *offset = 100; 
     return *offset; 
    } 

    return 0; 
} 

struct file_operations test_fops = { 
    .owner = THIS_MODULE, 
    .read = test_read, 
}; 

static int __init my_module_init(void) 
{ 
    struct proc_dir_entry *entry; 

    printk("We are testing now!!\n"); 
    entry = create_proc_entry("test", S_IFREG | S_IRUGO, NULL); 
    if (!entry) 
     printk("Failed to creats proc entry test\n"); 

    entry->proc_fops = &test_fops; 
    return 0; 
} 
module_init(my_module_init); 

從用戶空間應用程序,我讀我的/proc進入和一切正常。

查看copy_to_user()的源代碼,它說它也是簡單的memcpy(),我們只是試圖檢查指針是否有效,或者是否使用access_ok和執行memcpy。

所以我的理解目前是,如果我們肯定我們傳遞指針,的memcpy()總是可以代替copy_to_user的使用。

如果我的理解不正確,請糾正我,並且copy_to_user工作和memcpy()失敗的任何示例將非常有用。謝謝。

+0

這是因爲分頁。 – Linuxios 2013-02-20 01:22:11

+0

@Linuxios對不起,但你能解釋一個更多的littl。我無法證明內核能夠完美複製,我也無法在copy_to_user的源代碼中看到與分頁有關的任何內容。你能否詳細說明一下? – 2013-02-20 01:25:07

+1

@Sandy:假設的問題:您正在使用一個32位系統和16 GB的RAM。 memcpy會工作嗎? – 2013-02-20 02:31:39

回答

23

這有幾個原因。

首先,安全。由於內核可以寫入任何它想要的地址,如果你只是使用你得到的用戶空間地址並使用memcpy,攻擊者就可以寫入另一個進程的頁面,這是一個巨大的安全問題。 copy_to_user檢查目標頁面是否可由當前進程寫入。

還有一些體系結構考慮因素。例如,在x86上,目標頁面必須固定在內存中。在某些體系結構中,您可能需要特殊說明。等等。 Linux內核非常便攜的目標需要這種抽象。

+6

+1。不只是另一個過程。對於3G/1G內存拆分,「用戶」進程可能會嘗試重寫內核內存。如果你的數據是用來修改內核的代碼,這可能特別有用。許多CPU都有用戶模式和超級用戶模式。即使在MMU中,「memcpy()」也不好。 – 2013-02-21 00:13:13

+0

@BillPringlemeir:沒錯。感謝+1。 – Linuxios 2013-02-21 00:30:57