2

私はOSクラスのプロジェクトを仕上げていますが、データをユーザー空間からカーネルに安全にコピーし、カーネルからユーザー空間に戻すことに関係するいくつかのこと、およびこの情報を適切に破棄する方法を理解できません。

いくつかのシステムコールがあるとします:

//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. ポインター*dataが ではないことを検証しますnull
2. 検証するlength < 0
3. 使用する必要があるaccess_ok. ただし、両方の機能に使用する必要があるのか​​、long sys_into()
3 のみに使用する必要があるのか​​ はわかりません。 kmalloc(length) を使用してカーネルにコピーするときに、バイト数を割り当て、実際にこのメモリを割り当てることができることを確認します。
4. 最後にcopy_from_user&copy_to_userを使用してデータをコピーします。

これまでのところ、ほとんど情報が見つかりませんでした。1. 「Linux カーネル プログラミング」のソース コードの例(ご指摘のとおり、Linux カーネル開発の例は危険です)。2. http://www.quora.com/Linux-Kernel/How-does-copy_to_user-work

ありがとう !!!

4

1 に答える 1

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(void __user * に変更する必要があります。 uaddr, int __user *ulen)、コードは次のように変更されます。

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 バッファを使用しない方がよいでしょう。初期化中に十分な大きさの1つのカーネルバッファーをkmallocする方が良いですが。

于 2013-03-13T06:42:31.420 に答える