Saya ingin menentukan proses mana yang memiliki ujung soket UNIX.
Secara khusus, saya bertanya tentang yang dibuat dengan socketpair()
, meskipun masalahnya sama untuk setiap soket UNIX.
Saya punya program parent
yang membuat a socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
, dan fork()
s. Proses induk ditutup fds[1]
dan terus fds[0]
berkomunikasi. Anak melakukan yang sebaliknya close(fds[0]); s=fds[1]
,. Kemudian anak exec()
itu program lain child1
,. Keduanya dapat berkomunikasi bolak-balik melalui soketpair ini.
Sekarang, katakanlah saya tahu siapa parent
itu, tetapi saya ingin mencari tahu siapa child1
itu. Bagaimana saya melakukan ini?
Ada beberapa alat yang saya miliki, tetapi tidak ada yang bisa memberi tahu saya proses mana yang ada di ujung soket. Saya telah mencoba:
lsof -c progname
lsof -c parent -c child1
ls -l /proc/$(pidof server)/fd
cat /proc/net/unix
Pada dasarnya, saya dapat melihat dua soket, dan segala sesuatu tentang mereka, tetapi tidak dapat mengatakan bahwa mereka terhubung. Saya mencoba untuk menentukan FD mana dalam orangtua yang berkomunikasi dengan proses anak mana.
sumber
socketpair
, dan kedua ujung soket tidak berkorelasi kecuali dengan jenis spesifiksocketpair
metode . Untuk soket unix, adaunix_socketpair
di `net / unix / af_unix.c . Akan menyenangkan untuk memiliki informasi ini untuk pipa juga.Linux-3.3 dan yang lebih baru.
Di Linux, karena kernel versi 3.3 (dan asalkan
UNIX_DIAG
fitur dibangun di dalam kernel), rekan dari soket domain unix yang diberikan (termasuk soket pasang) dapat diperoleh dengan menggunakan API berbasis netlink baru .lsof
sejak versi 4.89 dapat menggunakan API itu:Akan mencantumkan semua soket domain Unix yang memiliki proses yang namanya dimulai dengan
Xorg
kedua ujungnya dalam format yang mirip dengan:Jika versi Anda
lsof
terlalu lama, ada beberapa opsi lagi.The
ss
utilitas (dariiproute2
) yang menggunakan yang API yang sama untuk mengambil dan menampilkan informasi dalam daftar unix domain sockets pada sistem termasuk informasi rekan.Soket diidentifikasi oleh nomor inode mereka . Perhatikan bahwa ini tidak terkait dengan inode sistem file dari file socket.
Misalnya di:
dikatakan bahwa soket 3435997 (yang terikat ke soket ABSTRAK
/tmp/.X11-unix/X0
) terhubung dengan soket 3435996.-p
Opsi ini dapat memberi tahu Anda proses mana yang membuat soket itu terbuka. Itu melakukan itu dengan melakukan beberapareadlink
s/proc/$pid/fd/*
, sehingga hanya bisa melakukan itu pada proses yang Anda miliki (kecuali Andaroot
). Misalnya di sini:Untuk mengetahui proses apa yang telah 3435996, Anda dapat mencari entri sendiri di output dari
ss -xp
:Anda juga dapat menggunakan skrip ini sebagai pembungkus
lsof
untuk dengan mudah menampilkan informasi yang relevan di sana:Sebagai contoh:
Sebelum linux-3.3
Linux API lama untuk mengambil informasi soket unix adalah melalui
/proc/net/unix
file teks. Ini mencantumkan semua soket domain Unix (termasuk soketnya). Bidang pertama di sana (jika tidak disembunyikan untuk non-pengguna super dengankernel.kptr_restrict
parameter sysctl) seperti yang sudah dijelaskan oleh @Totor berisi alamat kernel dari suatuunix_sock
struktur yang berisipeer
bidang yang menunjuk ke rekan yang sesuaiunix_sock
. Ini juga merupakanlsof
keluaran untukDEVICE
kolom pada soket Unix.Sekarang mendapatkan nilai
peer
bidang itu berarti bisa membaca memori kernel dan mengetahui offsetpeer
bidang itu berkaitan denganunix_sock
alamat.Beberapa
gdb
berbasis dansystemtap
berbasis solusi telah diberikan tetapi mereka memerlukangdb
/systemtap
dan Linux kernel simbol debug untuk kernel yang berjalan yang diinstal yang umumnya tidak terjadi pada sistem produksi.Hardcoding of the offset sebenarnya bukan pilihan karena bervariasi dengan versi kernel.
Sekarang kita dapat menggunakan pendekatan heuristik untuk menentukan offset: minta alat kita membuat dummy
socketpair
(lalu kita tahu alamat kedua rekan), dan cari alamat rekan di sekitar memori di ujung lainnya untuk menentukan offset.Berikut ini adalah skrip proof-of-concept yang tidak hanya menggunakan
perl
(berhasil diuji dengan kernel 2.4.27 dan 2.6.32 pada i386 dan 3.13 dan 3.16 pada amd64). Seperti di atas, ini berfungsi sebagai pembungkuslsof
:Sebagai contoh:
Ini skripnya:
sumber
lsof
penulis.ss
tidak melakukan hal ini? Agak di atas kepala saya, tetapiss -px
daftar banyak soket unix dengan informasi rekan seperti: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
dan judul kolom adalah ...State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
lsof -c terminology
bisa, saya bisa melihatterminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAM
tetapi jika saya melakukannyass -px | grep terminology
saya mendapatkan:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
Erkki Seppala sebenarnya memiliki alat yang mengambil informasi ini dari kernel Linux dengan gdb .. Ini tersedia di sini .
sumber
Sejak kernel 3.3
Anda sekarang dapat memperoleh informasi ini dengan :
ss
Sekarang Anda dapat melihat
Peer
ID di kolom (nomor inode) yang sesuai dengan ID lain diLocal
kolom. ID yang cocok adalah dua ujung soket.Catatan:
UNIX_DIAG
Opsi ini harus diaktifkan di kernel Anda.Sebelum kernel 3.3
Linux tidak memaparkan informasi ini ke userland.
Namun, dengan melihat ke dalam memori kernel , kita dapat mengakses informasi ini.
Catatan: Jawaban ini melakukannya dengan menggunakan
gdb
, namun, lihat jawaban @ StéphaneChazelas yang lebih rinci dalam hal ini.Ada 2 soket berbeda, 1 mendengarkan dan 1 didirikan. Nomor heksa adalah alamat ke
unix_sock
struktur kernel yang sesuai , yang memilikipeer
atribut sebagai alamat ujung soket yang lain (juga merupakanunix_sock
contoh struktur).Sekarang kita dapat menggunakan
gdb
untuk menemukan dipeer
dalam memori kernel:Ini dia, ujung soket lainnya dipegang oleh
mysql
, PID 14815.Kernel Anda harus dikompilasi
KCORE_ELF
untuk digunakan/proc/kcore
. Anda juga memerlukan versi kernel image Anda dengan simbol debugging. Pada Debian 7,apt-get install linux-image-3.2.0-4-amd64-dbg
akan menyediakan file ini.Tidak perlu untuk image kernel yang dapat di-debuggable ...
Jika Anda tidak memiliki (atau tidak ingin menyimpan) citra kernel debugging pada sistem, Anda dapat memberikan
gdb
memori offset untuk mengaksespeer
nilai "secara manual" . Nilai offset ini biasanya berbeda dengan versi kernel atau arsitektur.Pada kernel saya, saya tahu offsetnya adalah 680 byte, yaitu 85 kali 64 bit. Jadi saya bisa melakukan:
Voa, hasil yang sama seperti di atas.
Jika Anda memiliki kernel yang sama berjalan di beberapa mesin, lebih mudah untuk menggunakan varian ini karena Anda tidak memerlukan gambar debug, hanya nilai offset.
Untuk (dengan mudah) menemukan nilai offset ini pada awalnya, Anda memang membutuhkan gambar debug:
Ini dia, 680 byte, ini adalah 85 x 64 bit, atau 170 x 32 bit.
Sebagian besar penghargaan untuk jawaban ini diberikan ke MvG .
sumber
Jika pada sistem Linux baru-baru ini dengan tap sistem yang berfungsi (1,8 atau lebih baru), Anda dapat menggunakan skrip di bawah ini untuk memposting-proses output dari
lsof
:Sebagai contoh:
(jika Anda melihat 0x000000000000000000 di atas bukannya 0xffff ..., itu karena
kernel.kptr_restrict
parameter sysctl diatur pada sistem Anda yang menyebabkan pointer kernel disembunyikan dari proses yang tidak istimewa, dalam hal ini Anda harus menjalankanlsof
sebagai root untuk mendapatkan hasil yang bermakna).Script ini tidak berusaha untuk mengatasi nama file socket dengan karakter baris baru, tetapi juga tidak
lsof
(juga tidaklsof
mengatasi kekosongan atau titik dua).systemtap
di sini digunakan untuk membuang alamat dan alamat rekan semuaunix_sock
struktur dalamunix_socket_table
hash di kernel.Hanya diuji pada Linux 3.16 amd64 dengan systemtap 2.6, dan 3.13 dengan 2.3.
sumber
parse error: unknown statistic operator @var
: apakah saya melewatkan sesuatu?@var
ditambahkan di systemtap 1.8, 2012-06-17 (terbaru 2.7)4,89 dari lsof mendukung menampilkan opsi titik akhir.
Dikutip dari lsof.8:
Contoh output:
sumber
Karena ada kernel Linux 4.2
CONFIG_UNIX_DIAG
, yang menyediakan informasi tambahan tentang soket domain UNIX, yaitu informasiVirtual File System
(VFS), yang berisi informasi yang sejauh ini tidak ada untuk menghubungkan Inode dari jalur ke proses. Ini sudah bisa ditanyakan menggunakanss
alat dari iproute2 dimulai dengan versi v4.19.0 ~ 55 :Nomor perangkat dan jalur Inode dapat Anda peroleh
ss
juga mendukung pemfilteran:tetapi perlu diketahui bahwa ini mungkin tidak mencantumkan soket yang tepat untuk Anda, karena proses jahat mungkin mengganti nama soket asli Anda dan menggantinya dengan yang jahat itu sendiri:
lsof /tmp/socket
,fuser /tmp/socket
danss --processes --unix --all --extended 'sport = /tmp/socket'
semuanya akan mendaftar proses aslinya, bukan pengganti yang jahat. Alih-alih gunakan sesuatu seperti ini:Atau tulis program litte Anda sendiri berdasarkan template yang terdapat di man 7 sock_diag .
sumber