Dato un ID finestra X11, c'è un modo per trovare l'ID del processo che lo ha creato?
Ovviamente questo non è sempre possibile, ad esempio se la finestra è arrivata tramite una connessione TCP. In tal caso, vorrei l'IP e la porta associati all'estremità remota.
La domanda è stata posta in precedenza su Stack Overflow e un metodo proposto consisteva nell'utilizzare il _NET_WM_PID
proprietà. Ma questo è impostato dall'applicazione. C'è un modo per farlo se l'applicazione non funziona bene?
Risposta accettata:
A meno che il tuo server X non supporti XResQueryClientIds
dall'estensione X-Resource v1.2 non conosco facile modo per affidabile ID processo di richiesta. Ci sono però altri modi.
Se hai solo una finestra di fronte a te e non conosci ancora il suo ID, è facile scoprirlo. Basta aprire un terminale vicino alla finestra in questione, eseguire xwininfo
lì e fare clic su quella finestra. xwininfo
ti mostrerà l'id della finestra.
Quindi supponiamo che tu conosca un window-id, ad es. 0x1600045 e vuoi trovare qual è il processo che lo possiede.
Il modo più semplice per verificare a chi appartiene quella finestra è eseguire XKillClient per essa, ad esempio:
xkill -id 0x1600045
e vedere quale processo è appena morto. Ma solo se non ti dispiace ucciderlo ovviamente!
Un altro modo semplice ma inaffidabile è controllare il suo _NET_WM_PID
e WM_CLIENT_MACHINE
proprietà:
xprop -id 0x1600045
Ecco quali strumenti come xlsclients
e xrestop
fare.
Sfortunatamente queste informazioni potrebbero essere errate non solo perché il processo era malvagio e li ha cambiati, ma anche perché era difettoso. Ad esempio, dopo alcuni arresti anomali/riavvii di Firefox ho visto finestre orfane (dal plug-in flash, immagino) con _NET_WM_PID
indicando un processo, morto molto tempo fa.
Un modo alternativo è correre
xwininfo -root -tree
e controlla le proprietà dei genitori della finestra in questione. Questo potrebbe anche darti alcuni suggerimenti sulle origini della finestra.
Ma! Anche se potresti non trovare quale processo ha creato quella finestra, c'è ancora un modo per trovare da dove quel processo si è connesso a X-server. E questo è per i veri hacker. 🙂
Il window-id 0x1600045 che conosci con i bit inferiori azzerati (cioè 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 clients[], e per ogni client la sua "base" è memorizzata nella variabile clients[i]->clientAsMask. Per trovare X-socket, corrispondente a quel client, devi collegarti a X-server con gdb
, passa sopra l'array clients[], trova il client con quel clientAsMask
e stampa il suo descrittore di socket, memorizzato in ((OsCommPtr)(clients[i]->osPrivate))->fd.
Potrebbero esserci molti X-client collegati, quindi per non controllarli tutti manualmente, utilizziamo 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 la presa, puoi controllare chi è connesso ad essa e finalmente trovare il processo.
Correlati:come scaricare un'app dal negozio di Windows 10 per eseguire il sideload?
AVVISO :NON collegare gdb all'X-server dall'interno dell'X-server. gdb sospende il processo a cui si collega, quindi se ti colleghi ad esso dall'interno di X-session, congelerai il tuo server X e non sarai in grado di interagire con gdb. Devi passare al terminale di testo (Ctrl+Alt+F2
) o connettiti alla tua macchina tramite ssh.
Esempio:
-
Trova il PID del tuo server X:
$ 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 di clienti è 0x1600000. Collega a X-server e trova il descrittore di socket client per quella base di client. Avrai bisogno delle informazioni di debug
installate per X-server (pacchetto -debuginfo per le 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 qual è quella presa:$ 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 tramite TCP, quindi puoi andare alla macchina 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 il PID che lo tiene:$ 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 :Ci sono più opzioni ora come visto in Chi ha l'altra estremità di questa coppia di socket Unix?. Con Linux 3.3 o versioni successive e con lsof
4.89 o superiore, puoi sostituire i punti da 3 a 5 di cui 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.