私はいくつかの調査を行ってきましたが、このマクロについて少し混乱しています。うまくいけば、誰かが私にいくつかのガイダンスを与えることができます. 私はいくつかのioctlコード(私が継承したもので、書いたものではありません)を持っておりaccess_ok()
、ユーザー空間からデータをコピーする前にチェックするかどうかを最初に確認します:
#define __lddk_copy_from_user(a,b,c) copy_from_user(a,b,c)
#define __lddk_copy_to_user(a,b,c) copy_to_user(a,b,c)
long can_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
case COMMAND:
if(! access_ok(VERIFY_READ, (void *)arg, sizeof(Message_par_t)))
return(retval);
if(! access_ok(VERIFY_WRITE, (void *)arg, sizeof(Message_par_t)))
return(retval);
argp = &Command;
__lddk_copy_from_user( (void *) argp,(Command_par_t *) arg, sizeof(Command_par_t));
したがって、コードは問題なく機能しますが、必要かどうかはわかりません。最初の質問は、access_ok の戻りに関する次の説明から来ています。
- 領域がアクセス可能である可能性が高い場合、関数はゼロ以外を返します (ただし、アクセスしても -EFAULT になる場合があります)。この関数は、アドレスがカーネルではなくユーザー空間にある可能性が高いことを確認するだけです。
これは、チェックしているポインターがおそらくユーザー空間で初期化されていることを確認するだけで、実際には何もしないことを意味しますか? ユーザー空間の呼び出し以外ではこの関数に入ることができず、このデバイスに対して有効なファイル記述子を開かない限り発生しないことがわかっているので、これは本当に必要ですか? NULL ポインターを取得していないことを確認するよりも安全ですか?
2 番目の質問は、次の説明から来ています。
- type 引数は、VERIFY_READ または VERIFY_WRITE として指定できます。VERIFY_WRITE シンボリックは、メモリ領域が読み取り可能か書き込み可能かを識別します。
これは、コードの最初のチェックが冗長であることを意味しますか? 書き込み可能な領域をチェックする場合、景品として読み取り可能になりますか?
私は x86 アーキテクチャを使用しているので、access_ok() と __range_no_ok() の定義は、次のように /usr/src/linux-3.1.10-1.16/arch/x86/include/asm/uaccess.h のものです。
#define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0))
#define __range_not_ok(addr, size) \
({ \
unsigned long flag, roksum; \
__chk_user_ptr(addr); \
asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \
: "=&r" (flag), "=r" (roksum) \
: "1" (addr), "g" ((long)(size)), \
"rm" (current_thread_info()->addr_limit.seg)); \
flag; \
})