Linux 上的跨程序複製
我想複製一個在 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/stdin
並popen
輸入這樣的輸入(%d
您要獲取的 fd 在哪裡,並且%s
是您之前創建並正在偵聽的 unix 套接字的路徑):call pts_gift_fd("%s", %d) detach quit