場合によっては、ファイルシステムをマウント解除するか、ループデバイスを取り外す必要がありますが、これは開かれbusy
たファイルディスクリプタのため、またはsmb
サーバープロセスによるものです。
強制的に削除するには、問題のあるプロセスを終了または試みることができますが、これはkill -SIGTERM
接続を閉じますsmb
(開いているファイルの一部を閉じる必要はありません)。
プロセスが特定のファイル記述子を強制的に閉じる賢い方法を説明します。ここgdb
しかし、close(fd)
これは危険に見えます。閉じた記述子がリサイクルされるとどうなりますか?プロセスは、まったく別のファイルを参照していることを認識せずに、以前のストレージ記述子を使用している可能性があります。
アイデアがありますが、どのような落とし穴があるのかわかりません。使用してgdb
開き/dev/null
(O_WRONLY
編集:より良い代替案として提案されたコメントO_PATH
)dup2
、問題のファイルディスクリプタを閉じてディスクリプタを再利用します/dev/null
。これにより、ファイル記述子への読み取りまたは書き込みが失敗します。
このように:
sudo gdb -p 234532
(gdb) set $dummy_fd = open("/dev/null", 0x200000) // O_PATH
(gdb) p dup2($dummy_fd, offending_fd)
(gdb) p close($dummy_fd)
(gdb) detach
(gdb) quit
何が間違っている可能性がありますか?
答え1
プロセスを操作することはほとんど安全ではありませんが、gdb
緊急事態が発生し、プロセスをパブリックに保ち、関連するすべてのリスクとコードを理解する必要がある場合に必要になる場合があります。
ほとんどの場合、単にプロセスを終了します。ただし、状況によっては、環境、関連システムおよびプロセスの所有者、プロセスの実行作業、「終了可能」に関する事項があるかどうかによって異なります。 「いいえ、誰に最初に連絡してください。」などの問題が解決されると、これらの詳細はポストミーティングで解決する必要があるかもしれません。計画された移行がある場合は、事前に確認するのが最善です。開いているプロセスがある場合は、緊急でない状況(移行時に早朝にのみ実行されるcronジョブまたはその他のスケジュールされたジョブ)で処理できる問題のファイル記述子を指定します。日中に確認してください)
書き込み専用 vs.読書対。読み書き
O_WRONLY
すべてのファイルディスクリプタが書き込み専用ではないため、ファイルディスクリプタを再度開くというアイデアは問題があります。 John ViegaとMatt Messierは、「CおよびC ++のセキュリティプログラミングガイド」の標準出力および標準エラーとは異なり、標準入力を処理するより微妙なアプローチをとります(25ページ、「ファイル記述子を安全に管理する」)。
static int open_devnull(int fd) {
FILE *f = 0;
if (!fd) f = freopen(_PATH_DEVNULL, "rb", stdin);
else if (fd == 1) f = freopen(_PATH_DEVNULL, "wb", stdout);
else if (fd == 2) f = freopen(_PATH_DEVNULL, "wb", stderr);
return (f && fileno(f) == fd);
}
この場合、gdb
記述子(またはハンドル)が読み取り専用、読み取り/書き込み、または書き込み専用であることを確認し、適切な置換を有効にする必要があります。そうでない場合は、かつて読み取り専用であったハンドルが書き込み専用になり、プロセスがハンドルから読み取ろうとすると不要なエラーが発生します。FILE *
/dev/null
どのような問題が発生する可能性がありますか?
ファイルディスクリプタ(および
FILE *
ハンドル)が後ろから改ざんされたときにプロセスが正確にどのように機能するかはプロセスに依存し、そのディスクリプタが「悪夢モード」で使用されていない場合は「何も」と同じです。は異なります。更新されていないデータ、適切なファイル終了インジケータがない、またはその他の予期しない問題が発生したため、どこかにファイルが破損しています。
ハンドルの場合は、ハンドルを閉じる前に呼び出しを追加すると役に立つ場合があり、ダブルバッファリングやその他の問題が発生する可能性があります。これはFILE *
、ソースコードが何をして期待しているのかを正確に知らずにfflush(3)
ランダム呼び出しを実行したときに発生する可能性があるいくつかのリスクの1つです。ソフトウェアは、gdb
処理が必要な場合がある記述子またはハンドルの上に追加の複雑さ階層を構築することもできます。サルパッチコードは簡単にサルレンチに置き換えることができます。fd
FILE *
一般化する
プロセスに標準シャットダウン信号を送信すると、システムが正常にシャットダウンしたかのようにリソースを適切にシャットダウンする機会が与えられます。プロセスを操作すると、gdb
状況が正しく終了しなくなり、状況がさらに悪化する可能性があります。
答え2
O_WRONLYを使用して/ dev / nullを開き、dup2を使用して問題のあるファイル記述子を閉じて、その記述子を/ dev / nullに再使用します。これにより、ファイル記述子への読み取りまたは書き込みが失敗します。
記述子を にコピーしても書き込み/dev/null
は行われません。失敗する、しかし成功と読書は成功そして0(eof)を返します。
これはあなたが望むものかもしれないし、そうでないかもしれません。
O_WRONLY|O_RDWR
Linuxでは、flags = 3(別名)を使用してファイルを開くこともできます。O_NOACCESS
これにより読み取りまたは書き込みが失敗しますEBADF
。
ファイルはioctlでのみ動作します。これは、他の回答やコメントに記載されていないリスクをもたらします。読み書きは、ファイル記述子で実行される唯一の操作ではありません。 (lseek
または何をftruncate
?)。
修正する:
私は文書化されていないよりも優れていることを発見しましたO_WRONLY|O_RDWR
。O_PATH = 010000000 / 0x200000
open(2) マンページによると:
O_PATH (since Linux 2.6.39) Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform opera- tions that act purely at the file descriptor level. The file itself is not opened, and other file operations (e.g., read(2), write(2), fchmod(2), fchown(2), fgetxattr(2), mmap(2)) fail with the error EBADF. The following operations can be performed on the resulting file descriptor: * close(2); fchdir(2) (since Linux 3.5); fstat(2) (since Linux 3.6). * Duplicating the file descriptor (dup(2), fcntl(2) F_DUPFD, etc.).