2

linuxシステムコールに渡されたすべてのパラメータ値を出力したい。ioctl()たとえば、の場合、次のプロトタイプと印刷ステートメントがあります。

asmlinkage long our_sys_ioctl(unsigned int fd ,  unsigned int cmd , unsigned long arg)
{
    printk ("fd=%u, cmd=%u and arg=%lu \n ", fd, cmd, arg);
    return original_call_ioctl(fd , cmd , arg);
}

私は理解しfdています、はドライバーファイルのファイル記述子であり、cmdドライバー、ioctl番号、操作のタイプ、およびパラメーターのサイズを定義します。しかし、私はargパラメータについて混乱しています。それはメモリへのポインタであるか、ほとんどのドキュメントで呼ばれている単なる即時値です。

このパラメータを使用して、ポインタの代わりに上記のようにarg渡された場合、どのようにメモリコンテンツを取得できますか?unsigned long arg

4

3 に答える 3

5

ioctlのargパラメーターは、汎用vfsレベルでは不透明です。それをどのように解釈するかは、実際にそれを処理するドライバーまたはファイルシステム次第です。したがって、ユーザースペースメモリへのポインタである場合もあれば、インデックスやフラグなどである場合もあります。未使用で、通常は0で渡される場合もあります。

たとえば、次のTCSBRKPioctlの実装を見てdrivers/tty/tty_io.cください。

long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
//...
       case TCSBRKP:   /* support for POSIX tcsendbreak() */
            return send_break(tty, arg ? arg*100 : 250);

ioctl_list(2)マニュアルページを見ると、さまざまなioctlが取るパラメータを確認できます。intまたは他の非ポインタパラメータを持つそのリストのすべてのエントリは、他の例です。

だからあなたは次のようなことをすることができます

    void __user *argp = (void __user *) arg;

次に、copy_from_user()またはget_user()を使用してポイントするメモリを読み取りargますが、パラメータがポインタでない場合は失敗する可能性があります。また、一般的なioctl syscallでは、考えられるすべてのioctlの巨大なテーブルを実際に作成したくない場合があります。

于 2013-01-18T09:06:55.640 に答える
4

この回答にもリンクされているこのドキュメントは、部門でより明確にする必要があります。興味深い抜粋(私が太字のテキストを追加したもの)は次のようになります。

ユーザースペースでは、ioctlシステムコールには次のプロトタイプがあります。

int ioctl(int fd, unsigned long cmd, ...);

プロトタイプは、通常、関数に可変数の引数があることを示すドットがあるため、Unixシステムコールのリストで際立っています。ただし、実際のシステムでは、システムコールに可変数の引数を含めることはできません。ユーザープログラムはハードウェアの「ゲート」を介してのみシステムコールにアクセスできるため、システムコールには明確に定義されたプロトタイプが必要です。したがって、プロトタイプのドットは、可変数の引数ではなく、従来はとして識別されていた単一のオプションの引数char *argpを表します。ドットは、コンパイル中の型チェックを防ぐために単にあります。3番目の引数の実際の性質は、発行されている特定の制御コマンドによって異なります。(2番目の引数)。一部のコマンドは引数をとらず、一部は整数値を取り、一部は他のデータへのポインタを取ります。ポインターの使用は、任意のデータをioctl呼び出しに渡す方法です。その後、デバイスはユーザースペースと任意の量のデータを交換できます。

ioctl呼び出しの構造化されていない性質により、カーネル開発者の間で支持されなくなりました。各ioctlコマンドは、基本的に、個別の、通常は文書化されていないシステムコールであり、これらの呼び出しを監査する方法はありません。あらゆる種類の包括的な方法で。また、非構造化ioctl引数をすべてのシステムで同じように機能させることも困難です。たとえば、32ビットモードで実行されているユーザースペースプロセスを備えた64ビットシステムについて考えてみます。その結果、他のほぼすべての手段でその他の制御操作を実装するという強いプレッシャーがあります。考えられる代替案には、データストリームへのコマンドの埋め込み(この章の後半でこのアプローチについて説明します)、またはsysfsまたはドライバー固有のファイルシステムのいずれかの仮想ファイルシステムの使用が含まれます。(第14章でsysfsを見ていきます。)しかし、実際のデバイス操作にはioctlが最も簡単で最も簡単な選択であることが多いという事実は変わりません。

これは、デバイスドライバーの規則/内部に関する洞察に満ちた知識がなければ、ioctl引数を外部オブザーバーとして解釈する方法を理解する方法がないことを意味します。ioctl引数は、ユーザースペースの観点からは型指定されておらず、カーネルスペースでは、スペースを予約するためだけに扱われるため、どういうわけか大まかに型付けされていますunsigned longこれは「純粋な」数値またはスペースに収まる任意のビットシーケンスでありunsigned long integer、(非常に短い)文字列、(小さな)char配列、(小さな)構造体として使用できますが、エンディアンとアーキテクチャ固有に注意してくださいサイズ-デバイスのオンボードチップのオペコードを表すことも、タイプpuningによってフロートとして処理することもできます。

また、これは、一貫性のないデータ(間違ったデータだけでなく、間違ったタイプの間違ったデータ!)をドライバーに渡すことによって、物事を台無しにするのが非常に簡単であることを意味します。読み取りioctlで間違ったサイズの構造体へのポインターを渡すことによって)。

さらに数行:

[...]cmd引数は変更されずにユーザーから渡され、オプションの引数は、ユーザーが整数またはポインターとして指定したかどうかに関係なく、argの形式で渡されます。unsigned long呼び出し側プログラムが3番目の引数を渡さない場合、argドライバー操作によって受け取られる値は未定義です。追加の引数では型チェックが無効になっているため、無効な引数がioctlに渡された場合、コンパイラーは警告を表示できず、関連するバグを見つけるのは困難です。

とにかく、ヘッダーファイルとソースファイルを調べずに、デバイスドライバーのioctl呼び出しの「ブラインド」監査を試したい場合は、copy_from_user()を使用して、最初にargをポインターとして処理してみてください。即時値(またはエラーが発生した場合)の場合、その値をログに記録して外観を確認し、解釈を試みることができます(ただし、ドライバーコードを調べる代わりにioctlを逆にするのはなぜですか?)。成功すると、知識がなくても、さまざまなサイズのメモリを読み取ってログに記録し、デコードを試みることができます(ここでも、ソースが利用可能である限り、無意味です)。

より興味深い操作は、確かにioctlコード(cmd)をデコードすることです。これは、正しい方向を指し、その数値が関連付けられているドライバーを見つけることができるためです。ioctl定義の規則が次の場合、1つだけである必要があります。適用すると、とにかく異なるドライバーが同じ魔法の文字を使用できるため#define、「r」や「D」などを含むすべてのカーネルソースファイルをgrepする正規表現は、ioctl定義を検査するために多数のファイルを選択できます。 、関数番号と照合するよりも、いくつかまたはすべての間違ったものを分類する必要があり、正しい引数サイズを探すと検索が完了します。

よろしく。

于 2013-08-22T18:13:07.950 に答える
2

のプロトタイプはioctl次のようになっていることに注意してください。

int ioctl(int fildes, unsigned long request, ...);

最初の2つのパラメータが何であるかを確実に知っているだけです。この記事によると:

追加の引数はオプションであり、あるデバイスのioctl実装から別のデバイスの実装まで異なる場合があります。私の知る限り、3番目の議論は常に存在し、私はまだ3分の1以上を見つけていません。この3番目の引数は通常、構造体へのポインターのようです。これにより、任意の量のデータを両方向に渡すことができます。データは、ポインターを渡すだけで、ポインターが参照する構造によって定義されます。

...しかし、3番目のパラメーターしかない場合でも、それがリテラル値なのか、構造体へのポインターなのかはわかりません(予期されるパラメーターへの要求の明示的なマッピングがない場合)。

于 2013-01-18T02:07:52.483 に答える