2013-03-13 61 views
2

我正在完成OS類的項目,並且無法確定與將用戶空間的數據複製到內核以及從內核回到用戶空間的操作有關的幾件事情,以及如何妥善丟棄這些信息。關於將數據複製到Linux內核或從Linux內核複製數據的問題

說我有幾個系統調用:

//copies data into kernel space 
long sys_into(void __user *data, long length); 
// copies data into user space 
long sys_from(void __user *data, long length); 

在這兩種情況下long length是要複製的字節數。

件事我是能夠找出迄今:
1.驗證指針*datanull
2.驗證length < 0
3.我需要使用access_ok。但是,我不確定是否需要將它用於這兩種功能,或者僅用於long sys_into()
3.使用kmalloc(長度)複製到內核中以分配字節數並確保我實際上可以分配此內存。
4.最後使用copy_from_user & copy_to_user複製數據。

到目前爲止,我發現的信息非常少。 1. Source code example from "Linux kernel programming"(正如指出的,Linux內核開發中的例子很危險)。 2. http://www.quora.com/Linux-Kernel/How-does-copy_to_user-work

謝謝!

+0

爲什麼不使用'size_t'來表示大小的東西? – 2017-07-26 09:35:04

回答

3

我想你的考慮是正確的,我提供了一些代碼如下:

#define MAXIMUM_LENGTH 128 
char kaddr[MAXIMUM_LENGTH]; 

int sys_into(void __user *uaddr, int len) 
{ 
    if (len < 0 || len > MAXIMUM_LENGTH) 
     return -EINVAL; 
    if (len == 0) 
     return 0; 

    if (copy_from_user(kaddr, uaddr, len)) 
     return -EFAULT; 

    /* handling */ 

    return len; 
} 

int sys_from(void __user *uaddr, int len) 
{ 
    if (len > MAXIMUM_LENGTH) 
     len = MAXIMUM_LENGTH; 

    if (len < 0 || len > MAXIMUM_LENGTH) 
     return -EINVAL; 
    if (len) { 
     if (copy_to_user(uaddr, kaddr, len)) 
      return -EFAULT; 
} 

    return len; 
} 

其他考慮: (1)如果複印尺寸可能是真正的大和變化,您應該使用GET_USER(考慮)/ put_user()檢查,這意味着你必須改變sys_from()的參數表爲int sys_from(空隙__user * UADDR,INT __user *尤倫),該代碼將被更改爲:

int sys_from(void __user *uaddr, int __user *ulen) 
{ 
    int err; 
    int len; 

    err = get_user(len, ulen); 
    if (err) 
     return err; 
    if (len > MAXIMUM_LENGTH) 
     len = MAXIMUM_LENGTH; 
    if (len < 0 || len > MAXIMUM_LENGTH) 
     return -EINVAL; 
    if (len) { 
     if (copy_to_user(uaddr, kaddr, len)) 
      return -EFAULT; 
} 

    return __put_user(len, ulen); 
} 

(2 )如果可能的話,最好不要動態地使用kmalloc/kfree緩衝區經常。儘管在初始化時kmalloc的內核緩衝區足夠大,但它更好。