1

カーネル モジュールをコンパイルするときに、回避できない警告が表示されました。

まず、次の簡略化されたコードを見てください。

#define READ_CHUNK 100u
static int _procfs_write(struct file *file, const char *buf, unsigned long count, void *data)
{
    char command[READ_CHUNK];
    unsigned long left = count;
    while (left > 0)
    {
        unsigned int amount = left<READ_CHUNK?left:READ_CHUNK;    
        if (copy_from_user(command, buf, amount))
            return -EFAULT;
        buf += amount;
        left -= amount;
        /* process buffer */
    }
    return count;
}

私が得る警告は次のとおりです。

警告: 属性で宣言された 'copy_from_user_overflow' への呼び出し 警告: copy_from_user() バッファ サイズが正しいと証明されていません

ご覧のとおり、これは完全に間違っています。amount私が読んだデータのうち、問題ないことが証明されています! gccを沈黙させるために最後のパラメーターで使用できるというこのリンクを見つけましたが、うまくいきませんでした(私は書いた:min

if (copy_from_user(command, buf, min((unsigned long)amount, count)))

無駄に)。

これがクールで心配する必要がないことをgccに知らせる方法を知っている人はいますか?


これが発生する別の場所は、次のようなものです。

static int _procfs_write(struct file *file, const char *buf, unsigned long count, void *data)
{
    char *read_buffer = vmalloc(count * sizeof(*read_buffer));
    if (read_buffer == NULL)
        return -ENOMEM;
    if (copy_from_user(read_buffer, buf, count))
    {
        vfree(read_buffer);
        return -EFAULT;
    }
    /* process buffer */
    vfree(read_buffer);
    return count;
}

この場合、確かに正しいにもかかわらず、gcc からも同じ警告が表示されます。


これは正確なエラーです:

In file included from /usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess.h:571:0,
                 from <my source file>:7:
/usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess_32.h: In function ‘copy_from_user’:
/usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess_32.h:212:26: warning: call to ‘copy_from_user_overflow’ declared with attribute warning: copy_from_user() buffer size is not provably correct

カーネル バージョン: 2.6.35.9 に rtai を適用 (ご覧のとおり)

4

1 に答える 1

2

最初の例では、置き換えてみてください

min((unsigned long)amount, count)

min((unsigned long)READ_CHUNK, count)

これで、コンパイル時自体のコピーサイズが100バイトを超えないことが証明できるため、100バイトでもある宛先バッファーを上書きしないことをgccに納得させることができcommandます。

2番目の例では、コンパイル時にどちらread_bufferも認識されていません。countこのエラーで問題が発生しないようにするには、コンパイル時に評価可能なパラメーター(宛先バッファーとコピーサイズ)をに送信する必要があります。copy_from_user

メインラインのLinuxカーネルをチェックすると、カーネル内のマロックされたバッファーにユーザースペースデータを書き込んでいる例はほとんど見つかりません。したがって、コードが完全に安全である必要がある場合は、バッファーのマロッキングを排除する必要があると思います

PS:gccが、一部のバッファオーバーフロー攻撃を防ぐことができる制限付きバッファオーバーフロー保護メカニズムを実装する方法について読んでください。

于 2012-04-03T18:51:45.093 に答える