5

私は専門の C プログラマーではありません。GDB を使用したプログラムのデバッグに問題があります。(私が修正しようとしているバグは、ここで質問している問題とは関係ありません。) 私の問題は、バイナリをシェルから直接実行するとプログラムが正常に動作するのに、GDB を使用して実行するとプログラムがクラッシュすることです。

これは、20年以上前のデータベースソフトウェアで、元々はSolaris用に書かれていますが(私はそう思います)、Linuxに移植されて以来、setuidされています(ただし、rootにはなりません、神に感謝します) .

書き込み用にファイルを開こうとすると、GDB でプログラムがクラッシュします。GDB を使用して、次のシステム コールが失敗したためにクラッシュが発生したと判断できました。

fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);

明確化のために:は、存在してはならないpathロックファイルへのパスです。ロック ファイルが存在する場合、プログラムはこのシステム コールに到達する前に完全にシャットダウンします。

このシステム コールが失敗する理由がわかりません。なぜなら、1) このプログラムを実行するユーザーは、次のディレクトリに対する rwx パーミッションをpath持っており (これは、に格納されている変数の値を調べて確認しましたpath)、2) プログラムが正常に開くからです。 GDBを使用してデバッグしていないときに書き込むためのファイル。

できない理由があるのですか

4

1 に答える 1

8

キーは次のビットであることが判明しました。

...はsetuidです(ただし、ルートにはなりません、神に感謝します)。

プログラムを (任意の) デバッガーで (プログラムの停止と検査/変更機能を使用して) 実行すると、カーネルは非ルート setuid に対しても setuid 性を無効にします。

これは少し考えれば当然のことです。「ハイスコア」ファイルを保持し、「setuid games」を使用してこれを行うゲームを考えてみましょう。

fd = open(GAME_SCORE_FILE, open_mode, file_mode);
score_data = read_scores(fd);
/* set breakpoint here or so */
if (check_for_new_high_score(current_score, score_data)) {
    printf("congratulations, you've entered the High Scores records!\n");
    save_scores(fd, score_data);
}
close(fd);

「ハイスコア」ファイルへのアクセスは、ファイル許可によって保護されています。「ゲーム」ユーザーのみが書き込み可能です。

ただし、ゲームをデバッガーで実行する場合は、マークされた行にブレークポイントを設定し、 current_score データを非常に高い値に設定してから、プログラムを再開できます。

デバッガーが setuid プログラムの内部データを破損するのを防ぐために、カーネルは、デバッグ機能を有効にしてコードを実行するときに、単純に setuid 性を無効にします。デバッグに関係なく許可があることを示すことができる場合su(sudoまたは何でも)、そのユーザーとして gdb 自体を実行して、プログラムが "setuid された" ユーザーとして実行されるようにすることができます。

于 2013-11-05T00:05:50.073 に答える