無効なユーザースペースポインタをマクロaccess_ok(type、addr、size);に渡そうとしているため。。
したがって、提供されたポインタがカーネル空間メモリ内にある場合はカーネル空間領域にないことを確認し、それ以外の場合はtrueを返すため、この方法で目的の結果を確認できます。カーネルメモリの外部に任意のアドレスを提供することを受け入れることができます(提供されたアドレスが、このシステムコールを呼び出しているプロセスのアドレス空間ではない可能性があります。この場合、VERIFY_READまたはVERIFY_WRITEとして提供されるタイプが何をするかを決定します)。
access_ok()のマニュアルページから、http://mirror.linux.org.au/linux-mandocs/2.6.12.6/access_ok.htmlを参照してください。アーキテクチャによっては、この関数はおそらくポインタがユーザースペースの範囲内にあることを確認するだけであることに注意してください。この関数を呼び出した後でも、メモリアクセス関数は-EFAULTを返す場合があります。
カーネルにポインタを渡したい場合は、1->ポインタアドレスを含む1つの構造を定義するように行うことができます。2->カーネルモジュールまたはドライバーに同じ構造を追加します。したがって、カーネルとユーザーは構造について知っています。3->システムコールに1つのパラメータをとして追加しますchar __user var
。4->定義された構造のユーザースペースに1つの構造変数を作成し、ユーザースペースアプリケーションで呼び出すときにシステムコールに渡します。5->システムコール用にコードが定義されているkernel-moduleまたはdriver内で、ユーザースペースで使用したものと同じ構造の構造変数を作成します。そして今、あなたがやりたいことは何でもしてください。
`
struct new_struct
{
void *p; //set this pointer which you want to send...
};
//from user-application...
int main()
{
....
struct new_struct req_kernel;
your_system_call_function(...,(void *)&req_kernel,...);
}
//this is inside your kernel...
your_system_call(...,char __user optval,...)
{
.....
struct new_struct req;
if (copy_from_user(&req, optval, sizeof(req)))
return -EFAULT;
//now you have the address or pointer which you want in kernel with struct req...
}
`