2014-10-10 31 views
0

我有以下的系統調用:如何處理copy_from_user()中的頁面錯誤?

long do_print(int n, char *p){ 
    char tmp[n]; //allocate array of n bytes 
    int ret = copy_from_user(tmp,p,n); 
    if (!ret){ 
    //do something with tmp 
    } 
    return ret; 
} 

其返回n>5000非零值(我估計是因爲頁面錯誤的)。

如何強制複製成功。換句話說,如果系統調用返回非零值,我該怎麼辦?

回答

4

在棧上分配一個大數組並不是你應該或者真的可以做到的。 linux內核使用一個小堆棧,通常是2個內存頁面。如果您的char tmp[n];依賴於來自用戶空間的n,那麼同樣更危險的是,這會讓用戶空間可能使內核崩潰。在這種情況下,您必須動態分配內存,而不是在堆棧上使用緩衝區。

至於如果copy_from_user()失敗,用戶會欺騙內核,並將錯誤傳遞給內核。

處理這個問題的正常方法是從任何你正在執行的任務中解脫出來,並將-EFAULT傳遞迴用戶空間。

+0

在用戶空間代碼中,我確保將n個字節分配給指針。我該如何處理-EINVAL值? – user1734905 2014-10-10 08:08:09

+0

@ user1734905您可以像處理任何其他錯誤一樣處理它。此外,nos指的是你在內核堆棧上使用的數組的大小。你絕對不希望用戶空間能夠崩潰內核。 – tangrs 2014-10-10 08:31:37

+0

@ user1734905那麼也許在別的地方出了問題。你是否覈實過'n'在內核中與用戶空間代碼中的值相同?我不知道你在執行什麼(例如系統調用,字符設備中的read()函數等),但你可以看看其他的例子,例如, [this](http://lxr.free-electrons.com/source/block/ioctl.c#L25),它實現了ioctl()調用 - 在該示例中,如果copy_from_user()失敗,它將導致ioctl )在用戶空間返回-1,(和errno爲EFAULT)。不過,您需要修復代碼以便不在堆棧上分配。 – nos 2014-10-10 08:41:26

相關問題