Linuxでは、関係のないプロセスで実行されているファイル記述子をコピーしたいと思います。私は知っていますメッセージを送信(2)そしてSCM_RIGHTS
(例えばhttps://stackoverflow.com/questions/4489433/sending-file-descriptor-over-unix-domain-socket-and-select)、しかし、これは他のプロセスが協力している場合にのみ機能します。他のプロセスの積極的な協力を必要としないソリューションが必要です。また、ファイル記述子を最初に作成し、コピーをアーカイブしてから別のプロセスを作成できることもわかっていますが、他のプロセスが独自のファイル記述子を作成できるようにするソリューションが必要です。
ファイル記述子を見ることができます。
$ ls -l /proc/13115/fd/3
lrwx------ 1 pts pts 64 2013-05-04 13:15 /proc/13115/fd/3 -> socket:[19445454]
ただし、open("/proc/13115/fd/3", O_RDWR)
別のプロセスで実行するとエラーが返されます。対応するデバイスまたはアドレスがありません。。他の効率的な方法がありますか?一緒にいるかもしれない道?
答え1
これは意図的に設計されています。ファイル記述子を他のプロセスと共有することは明示的です。デフォルトでは、ファイル記述子はプロセス自身のメモリと同じくらいプライベートです。
いつものように、権利があれば道このプロセス中に呼び出しを含め、必要なすべての操作を実行できますsendmsg
。伝統的に、呼び出しはptrace
SELinux、機能、刑務所などのセキュリティ制限で実行する必要があり、ptrace
制限がさらに厳しくなる可能性があります。たとえば、デフォルトのUbuntu設定では、非ルートプロセスはptrace
AppArmorを介して独自のサブプロセスのみを呼び出すことができます。
強く使用するのは少し面倒ですptrace
。正しいデータを注入し、何も上書きしていないことを確認し、自分で整理する必要があります。だから私が提案するのは、ロータリー方式でコードを挿入し、既存のツールを使用してコードをトリガーすることです。
コードを含む小さな共有ライブラリを作成しsendmsg
、LD_PRELOAD
他のプロセスで使用できるようにします。ここにいくつかあります未テストスケルトンコードの欠落エラーチェック。
int pts_gift_fd (char *path, int fd) {
int sock;
struct sockaddr_un addr = {0};
struct msghdr msg = {0};
struct iovec iov = {0};
addr.sun_family = AF_UNIX;
strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
/* Populate msg, iov as in the code you've already found */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
connect(sock, (struct sockaddr*)&addr, sizeof(addr));
sendmsg(sock, &msg, 0);
close(sock);
}
その後、コードをトリガーするには、次のように実行してgdb -n -pid 13115 -batch -x /dev/stdin
入力popen
します(%d
インポートするfdはどこにあり、%s
以前に作成してリッスンしているUnixソケットのパスはどこにありますか?)。
call pts_gift_fd("%s", %d)
detach
quit
答え2
これができない理由は、無関係なプロセスのメモリにアクセスできないのと同じ理由です。はい他のプロセスのメモリの一部です。この情報が存在する唯一の理由/proc
は、カーネルがその情報を提供して読み取り専用であるためです。コピープロセスメモリ)。
ファイルに関連する場合は、そのファイルにアクセスしてみることができます。ソケットの場合は、次のようにスヌーピングできます。libpcapまたはそれから派生したもの。
デフォルトでは、状況は次のとおりです。ファイル記述子は(再)プロセスメモリの一部です。記述子にはカーネル空間に存在するデフォルトバッファがあります。プロセスがディスクリプタから読み書きするときに、対応するバッファへの書き込みまたは書き込みです。データ出力の場合、カーネルはバッファ(ハードウェアへ)を適切にフラッシュします。着信データの場合、プロセスがバッファをクリアすると、ハードウェアからバッファを再充填します。 AFAIK、いくつかの方法(libpcapなど)がありますが、これらのバッファは他のプロセスからアクセスできません。読むprocインターフェースと同様に、特定のカーネルインターフェースによって決定されるいくつかのデータ型は、プロセスのユーザー空間メモリからいくつかのデータを提供する可能性があります。