Я хочу определить, какой процесс имеет другой конец сокета UNIX.
В частности, я спрашиваю о том, что было создано с socketpair()
, хотя проблема та же для любого сокета UNIX.
У меня есть программа, parent
которая создает socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
, и fork()
с. Родительский процесс закрывается fds[1]
и продолжает fds[0]
общаться. Ребенок делает наоборот close(fds[0]); s=fds[1]
. Тогда у ребенка exec()
другая программа child1
. Эти двое могут общаться друг с другом через эту сокет-пару.
Теперь, скажем, я знаю, кто parent
есть, но я хочу выяснить, кто child1
есть. Как мне это сделать?
В моем распоряжении есть несколько инструментов, но ни один не может сказать мне, какой процесс находится на другом конце сокета. Я пытался:
lsof -c progname
lsof -c parent -c child1
ls -l /proc/$(pidof server)/fd
cat /proc/net/unix
В принципе, я вижу две розетки и все, что с ними связано, но не могу сказать, что они связаны. Я пытаюсь определить, какой FD у родителя взаимодействует с каким дочерним процессом.
источник
socketpair
, и два конца сокета не коррелированы, кроме как с помощьюsocketpair
метода, зависящего от типа . Для сокетов unix это находитсяunix_socketpair
в `net / unix / af_unix.c . Было бы неплохо иметь эту информацию и для труб.Linux-3.3 и выше.
В Linux, начиная с версии ядра 3.3 (и при условии, что эта
UNIX_DIAG
функция встроена в ядро), одноранговый узел данного сокета домена unix (включая пары сокетов) можно получить с помощью нового API на основе netlink .lsof
с версии 4.89 можно использовать этот API:Перечислит все доменные сокеты Unix, у которых есть процесс, имя которого начинается с
Xorg
любого конца в формате, подобном следующему:Если ваша версия
lsof
слишком старая, есть еще несколько вариантов.ss
Утилита (отiproute2
) использует тот же API для извлечения и отображения информации о списке сокетов домена UNIX в системе , включая информацию экспертной.Сокеты идентифицируются по их номеру инода . Обратите внимание, что это не связано с inode файловой системы файла сокета.
Например, в:
он говорит, что сокет 3435997 (который был связан с сокетом ABSTRACT
/tmp/.X11-unix/X0
) связан с сокетом 3435996.-p
Опция может сказать вам, какие процессы открыли этот сокет. Он делает это, делая некоторыеreadlink
с на/proc/$pid/fd/*
, так что он может сделать это только на процессы , которые вы владеете (если вы неroot
). Например здесь:Чтобы узнать, какой процесс (ы) имеет 3435996, вы можете найти его собственную запись в выводе
ss -xp
:Вы также можете использовать этот скрипт в качестве оболочки,
lsof
чтобы легко показать соответствующую информацию там:Например:
До Linux-3.3
Старый Linux API для получения информации о сокетах Unix через
/proc/net/unix
текстовый файл. В нем перечислены все доменные сокеты Unix (включая пары сокетов). Первое поле там (если оно не скрыто для не суперпользователей сkernel.kptr_restrict
параметром sysctl), как уже объяснено @Totor, содержит адрес ядраunix_sock
структуры, которая содержитpeer
поле, указывающее на соответствующий узелunix_sock
. Это также то, чтоlsof
выводитDEVICE
столбец на сокете Unix.Теперь получить значение этого
peer
поля означает, что вы можете прочитать память ядра и узнать смещение этогоpeer
поля относительноunix_sock
адреса.Некоторые решения на
gdb
основе и наsystemtap
основе уже были предоставлены, но для них требуетсяgdb
/systemtap
и символы отладки ядра Linux для устанавливаемого работающего ядра, что, как правило, не так в производственных системах.Жесткое кодирование смещения на самом деле не вариант, так как это зависит от версии ядра.
Теперь мы можем использовать эвристический подход при определении смещения: наш инструмент создаст фиктивную
socketpair
(тогда мы узнаем адрес обоих пиров) и поищем адрес пира вокруг памяти на другом конце, чтобы определить смещение.Вот сценарий проверки концепции, который делает именно это
perl
(успешно протестирован с ядром 2.4.27 и 2.6.32 на i386 и 3.13 и 3.16 на amd64). Как и выше, он работает как оболочкаlsof
:Например:
Вот сценарий:
источник
lsof
автору.ss
не делает этого? Это отчасти по моей голове, ноss -px
перечисляет множество сокетов Unix с информацией оusers: ("nacl_helper",pid=18992,fd=6),("chrome",pid=18987,fd=6),("chrome",pid=18975,fd=5)) u_str ESTAB\t0\t0\t/run/dbus/system_bus_socket 8760\t\t* 15068
State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
lsof -c terminology
я могу видеть,terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAM
но если я делаю,ss -px | grep terminology
я получаю:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
Эркки Сеппала на самом деле имеет инструмент, который получает эту информацию из ядра Linux с помощью gdb. Он доступен здесь .
источник
Начиная с ядра 3.3
Теперь вы можете получить эту информацию с :
ss
Теперь вы можете увидеть в
Peer
столбце идентификатор (номер индекса), который соответствует другому идентификатору вLocal
столбце. Соответствующие идентификаторы - это два конца сокета.Примечание:
UNIX_DIAG
опция должна быть включена в вашем ядре.До ядра 3.3
Linux не предоставил эту информацию пользователю.
Однако, просматривая память ядра , мы можем получить доступ к этой информации.
Примечание. Этот ответ можно сделать, используя
gdb
, однако, см. Ответ @ StéphaneChazelas, более подробный в этом отношении.Есть 2 разных сокета, 1 прослушивающий и 1 установленный. Шестнадцатеричное число - это адрес соответствующей
unix_sock
структуры ядра ,peer
атрибут которого является адресом другого конца сокета (такжеunix_sock
экземпляра структуры).Теперь мы можем использовать,
gdb
чтобы найтиpeer
внутреннюю память ядра:Вот, пожалуйста, другой конец розетки
mysql
, PID 14815.Ваше ядро должно быть скомпилировано
KCORE_ELF
для использования/proc/kcore
. Кроме того, вам нужна версия образа вашего ядра с символами отладки. На Debian 7apt-get install linux-image-3.2.0-4-amd64-dbg
предоставит этот файл.Нет необходимости в отлаживаемом образе ядра ...
Если у вас нет (или вы не хотите сохранять) отладочного образа ядра в системе, вы можете задать
gdb
смещение памяти для «ручного» доступа кpeer
значению. Это значение смещения обычно отличается в зависимости от версии ядра или архитектуры.На моем ядре я знаю, что смещение составляет 680 байт, то есть в 85 раз больше 64 бит. Так что я могу сделать:
Вуаля, тот же результат, что и выше.
Если у вас на одном компьютере работает одно и то же ядро, этот вариант проще использовать, потому что вам не нужен отладочный образ, только значение смещения.
Чтобы (легко) сначала обнаружить это значение смещения, вам необходимо изображение отладки:
Итак, 680 байт, это 85 x 64 бита или 170 x 32 бита.
Большая часть кредита на этот ответ идет в MvG .
источник
Если в недавней системе Linux с работающей системной вкладкой (1.8 или новее), вы можете использовать приведенный ниже скрипт для последующей обработки вывода
lsof
:Например:
(если вы видите 0x0000000000000000 выше вместо 0xffff ..., это потому, что в
kernel.kptr_restrict
вашей системе установлен параметр sysctl, который заставляет указатели ядра быть скрытыми от непривилегированных процессов, и в этом случае вам нужно будет запускатьlsof
от имени root, чтобы получить значимый результат).Этот сценарий не делает никаких попыток справиться с именами файлов сокетов с помощью символов новой строки, но не делает
lsof
(и неlsof
справляется с пробелами или двоеточиями).systemtap
здесь используется для вывода адреса и однорангового адреса всехunix_sock
структур вunix_socket_table
хеше в ядре.Проверено только на Linux 3.16 amd64 с системной тапой 2.6 и 3.13 с 2.3.
источник
parse error: unknown statistic operator @var
: я что-то пропустил?@var
был добавлен в systemtap 1.8, 2012-06-17 (последняя версия 2.7)4.89 из lsof поддерживает отображение параметров конечной точки.
Цитируется из lsof.8:
Пример вывода:
источник
Начиная с ядра Linux 4.2, существует
CONFIG_UNIX_DIAG
дополнительная информация о сокетах домена UNIX, а именно информацияVirtual File System
(VFS), которая содержит до сих пор недостающую информацию для связи Inode с путем к процессу. Его уже можно запросить с помощьюss
инструмента из iproute2, начиная с версии v4.19.0 ~ 55 :Номер устройства и путь Inode вы можете получить
ss
также поддерживает фильтрацию:но имейте в виду, что в этом списке может не указываться нужный сокет, поскольку злой процесс может переименовать ваш исходный сокет и заменить его собственным злым:
lsof /tmp/socket
,fuser /tmp/socket
иss --processes --unix --all --extended 'sport = /tmp/socket'
все перечислю оригинальный процесс, а не злую замену. Вместо этого используйте что-то вроде этого:Или напишите свою собственную программу на основе шаблона, содержащегося в man 7 sock_diag .
источник