Linux

Linux 上的跨程序複製

  • May 6, 2013

我想複製一個在 Linux 上不相關程序中執行的文件描述符。我知道*sendmsg(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)在另一個程序中執行會返回錯誤No such device or address。還有什麼可以工作的嗎?可能與ptrace

這是設計使然:與其他程序共享文件描述符是明確的。預設情況下,文件描述符與程序自己的記憶體一樣私有。

像往常一樣,如果你有權ptrace程序,你可以做任何你喜歡的事情,包括讓它呼叫sendmsg。傳統上,呼叫ptrace需要以相同的使用者 ID 執行;SELinux、功能、監獄等安全限制可以使ptrace限制性更強。例如,在預設的 Ubuntu 配置下,非 root 程序只能呼叫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/stdinpopen輸入這樣的輸入(%d您要獲取的 fd 在哪裡,並且%s是您之前創建並正在偵聽的 unix 套接字的路徑):

call pts_gift_fd("%s", %d)
detach
quit

引用自:https://unix.stackexchange.com/questions/74672