0

パラメータとして構造体ポインタを受け取るカーネル関数fooを書いています

void foo(struct struct1 *param)
{

    if(param!=NULL)
    {
        if(param->param1!=NULL)
        {
            if(param->param1->bool_value)
                Some code
        }
    }
    some code
}

この関数は、プロセスコンテキストで実行されます。上記の関数のこの行でクラッシュしました。if(param->param1->bool_value)。このクラッシュは1回限りのクラッシュであり、二度と発生することはありませんでした。

BADVAアドレスは、ユーザースペースアドレスを指します。このアドレスはparam1->bool_valueのアドレスですか?もしそうなら、カーネルモードコードはcopy_from_userを使用せずにこのアドレスにアクセスして読み取ることができますか?

4

2 に答える 2

2

param->param1初期化されていないか、上書きされている可能性があります。

初期化するときstruct1、常にそのメンバーをNULLに設定しますか?そうしないと、初期化されていないデータの使用に問題がある可能性があり、比較的簡単に処理できます。常にNULLに初期化する場合、他のコードがメンバーを上書きしている可能性があります。これは診断が難しいでしょう。

于 2012-10-10T12:05:20.720 に答える
1

テストとアクセスの間に構造が変更されていないことを (ロックを使用して) 確認しましたか? おそらくあなたは使うことができます

void foo(struct somestruct *const param)
{
    if (param) {
        struct otherstruct *const param1 = param->param1;

        if (param1 && param1->bool_value) {
            /* Do stuff */
        }
    }
}

C は の短絡ロジックを指定しているため、最も内側のテストで が NULL の場合&&、逆参照されないことに注意してください。param1param1

この種のアクセス パターン (最も外側の を除くif (param)) は、Linux カーネルでは非常に一般的です。注意すべき唯一のことは、他の CPU がまだ (キャッシュされたポインターを介して) アクセスしている間は解放されないように、破棄param1は何らかのロックによって保護されている必要があるということです。

于 2012-10-10T12:32:59.527 に答える