いくつかの背景:
リアルタイムプリエンプション用にパッチを適用した組み込みLinux ARM 4.1.33システムがあります。システムにはいくつかのカスタム修正カーネルコードが含まれており、時にはカーネルのバグが発生します。いくつかのデバッグの後、開発者の1人がカーネルスペースとユーザースペースの違いを理解しておらず、uaccess.hで定義された関数を使用せずにユーザースペースポインタを逆参照していることがわかりました。
その後、追加のカーネルエラーが発生するのを防ぐために、uaccess.hで定義された関数を使用するように問題の関数を修正しました。今すぐ修正が成功したことを確認しようとしています。しかし、元のカーネルエラーはランダムに発生し、時には一度に数日間発生しないため、元のコードから確実に再生成し、更新されたコードに表示されなくなったことを確認する方法を見つけたいと思います。
問題の関数はポインタを誤って使用しますが、ユーザー空間の値を正しく修正するためにポインタを使用しているようです(カーネルエラーが発生した場合を除く)。これは、ポインタのアドレスがユーザ空間とカーネル空間で「同じことを意味する」ことを示します。このような事実を考慮すると、そのような逆参照がカーネルエラーを引き起こす可能性があることを私が知っている唯一の理由は、そのアドレスを含むページがスワップで送信され、ページエラーを引き起こす場合です。ただし、フラッシュメモリの寿命が限られているため、システムでスワップが無効になっているため、このシナリオは少ない可能性があります。
質問:
カーネル空間内のユーザ空間ポインタの逆参照に関連するLinuxカーネルエラーの潜在的な原因は何ですか?修正を適用した後に発生しないことを確認するために、このようなカーネルエラーが発生するようにするにはどうすればよいですか?
答え1
ページが置き換えられる可能性に加えて、これが失敗する可能性がある2つの理由があります。
- ユーザーのアドレスから読む場合は、ページを読むことができる必要があります。作成と実行も同様です。
- ユーザー空間アドレスはこのプロセスに属しません。カーネルアドレスは物理アドレスに一貫して一対一にマッピングされますが、ユーザー空間の同じ仮想アドレスは現在のプロセスに応じて異なる物理アドレスを指すことがあります。
答え2
32ビットカーネルは、プロセスが4GBのアドレス空間(数ページを除く)を取得するようにコンパイルできます。これにより、すべてのユーザースペースポインタがカーネルスペース*で無効になります。しかし、あなたはこれまでやったことがわかります。
*衝突しないことがあります。任意のカーネルメモリを指すこともできますが、ここに書き込むとエラーが発生します。
答え3
現在存在するかどうかを確認することはできませんが、ページが現在の「書き込み時コピー」(おそらく以前の呼び出しを介して)に設定されている場合はfork()
そうなると思います。カーネルページは書き込み時にコピーしないでください。