A meno che il tuo X-server supporti XResQueryClientIds
dall'estensione X-Resource v1.2 non conosco un modo semplice per richiedere in modo affidabile l' ID del processo. Ci sono altri modi comunque.
Se hai solo una finestra davanti a te e non conosci ancora il suo ID - è facile scoprirlo. Basta aprire un terminale vicino alla finestra in questione, correre xwininfo
lì e fare clic su quella finestra. xwininfo
ti mostrerà l'ID finestra.
Supponiamo quindi che tu conosca un ID finestra, ad es. 0x1600045, e desideri trovare qual è il processo che lo possiede.
Il modo più semplice per verificare a chi appartiene quella finestra è eseguire XKillClient per questo, ovvero:
xkill -id 0x1600045
e vedi quale processo è appena morto. Ma solo se non ti dispiace ucciderlo ovviamente!
Un altro modo semplice ma inaffidabile è di controllarne le proprietà _NET_WM_PID
e le WM_CLIENT_MACHINE
proprietà:
xprop -id 0x1600045
Ecco cosa piacciono xlsclients
e xrestop
fanno gli strumenti .
Sfortunatamente queste informazioni potrebbero essere errate non solo perché il processo era malvagio e ha cambiato quelle, ma anche perché era difettoso. Ad esempio, dopo un arresto / riavvio di Firefox, ho visto finestre orfane (dal plug-in flash, immagino) con _NET_WM_PID
un processo che è morto molto tempo fa.
Un modo alternativo è quello di correre
xwininfo -root -tree
e controlla le proprietà dei genitori della finestra in questione. Ciò potrebbe anche darti alcuni suggerimenti sulle origini delle finestre.
Ma! Anche se potresti non trovare quale processo ha creato quella finestra, c'è ancora un modo per trovare da dove quel processo si è connesso all'X-server. E in questo modo è per veri hacker. :)
L'ID finestra 0x1600045 che si conosce con bit inferiori azzerati (ovvero 0x1600000) è una "base client". E tutti gli ID risorsa, allocati per quel client, sono "basati" su di esso (0x1600001, 0x1600002, 0x1600003, ecc.). X-server memorizza le informazioni sui suoi client nell'array client [] e per ogni client la sua "base" è memorizzata nei client [i] -> clientAsMask. Per trovare X-socket, corrispondente a quel client, è necessario collegarsi a X-server con gdb
, camminare sull'array client [], trovare client con quello clientAsMask
e stampare il suo descrittore socket, memorizzato in ((OsCommPtr) (client [i] - > osPrivate)) -> fd.
Potrebbero esserci molti client X collegati, quindi per non controllarli tutti manualmente, usiamo una funzione gdb:
define findclient
set $ii = 0
while ($ii < currentMaxClients)
if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0)
print ((OsCommPtr)(clients[$ii]->osPrivate))->fd
end
set $ii = $ii + 1
end
end
Quando trovi il socket, puoi controllare chi è collegato ad esso e infine trovare il processo.
ATTENZIONE : NON collegare gdb a X-server da INSIDE X-server. gdb sospende il processo a cui si allega, quindi se ci si collega da dentro X-session, si bloccherà il proprio X-server e non sarà in grado di interagire con gdb. È necessario passare al terminale di testo ( Ctrl+Alt+F2
) o connettersi al proprio computer tramite ssh.
Esempio:
Trova il PID del tuo X-server:
$ ps ax | grep X
1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
L'ID della finestra è 0x1600045, quindi la base client è 0x1600000. Collegarsi a X-server e trovare il descrittore del socket client per quella base client. Avrai bisogno di informazioni di debug installate per X-server (pacchetto -debuginfo per distribuzioni rpm o pacchetto -dbg per deb).
$ sudo gdb
(gdb) define findclient
Type commands for definition of "findclient".
End with a line saying just "end".
> set $ii = 0
> while ($ii < currentMaxClients)
> if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0)
> print ((OsCommPtr)(clients[$ii]->osPrivate))->fd
> end
> set $ii = $ii + 1
> end
> end
(gdb) attach 1237
(gdb) findclient 0x1600000
$1 = 31
(gdb) detach
(gdb) quit
Ora sai che il client è connesso a un socket del server 31. Usa lsof
per trovare cos'è quel socket:
$ sudo lsof -n | grep 1237 | grep 31
X 1237 root 31u unix 0xffff810008339340 8512422 socket
(qui "X" è il nome del processo, "1237" è il suo pid, "root" è l'utente da cui è in esecuzione, "31u" è un descrittore di socket)
Lì potresti vedere che il client è connesso su TCP, quindi puoi andare al computer da cui è connesso e controllare netstat -nap
lì per trovare il processo. Ma molto probabilmente vedrai un socket unix lì, come mostrato sopra, il che significa che è un client locale.
Per trovare una coppia per quel socket unix puoi usare la tecnica di MvG
(avrai anche bisogno di informazioni di debug per il tuo kernel installato):
$ sudo gdb -c /proc/kcore
(gdb) print ((struct unix_sock*)0xffff810008339340)->peer
$1 = (struct sock *) 0xffff810008339600
(gdb) quit
Ora che conosci il socket client, usa lsof
per trovare PID che lo trattiene:
$ sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
Questo è tutto. Il processo che mantiene quella finestra è "firefox" con ID processo 7725
Modifica 2017 : ora ci sono più opzioni come visto in Chi ha l'altra estremità di questa socket unix? . Con Linux 3.3 o versioni successive e con lsof
4.89 o versioni successive, è possibile sostituire i punti da 3 a 5 sopra con:
lsof +E -a -p 1237 -d 31
per scoprire chi si trova all'altra estremità del socket su fd 31 del processo X-server con ID 1237.