Chyba, że X-serwer obsługuje XResQueryClientIds
od X-Zasobami przedłużenie v1.2 nie znam łatwy sposób, aby niezawodnie żądania identyfikator procesu. Istnieją jednak inne sposoby.
Jeśli masz przed sobą okno i nie znasz jeszcze jego identyfikatora - łatwo je znaleźć. Po prostu otwórz terminal obok danego okna, uruchom xwininfo
tam i kliknij to okno. xwininfo
pokaże ci identyfikator okna.
Załóżmy więc, że znasz identyfikator okna, np. 0x1600045, i chcesz dowiedzieć się, jaki proces jest jego właścicielem.
Najłatwiejszym sposobem sprawdzenia, do kogo należy to okno, jest uruchomienie XKillClient dla niego, tj .:
xkill -id 0x1600045
i zobacz, który proces właśnie umarł. Ale tylko jeśli oczywiście nie masz nic przeciwko zabiciu go!
Innym łatwym, ale zawodnym sposobem jest sprawdzenie jego _NET_WM_PID
i WM_CLIENT_MACHINE
właściwości:
xprop -id 0x1600045
Właśnie takie narzędzia lubią xlsclients
i xrestop
robią.
Niestety te informacje mogą być niepoprawne nie tylko dlatego, że proces był zły i zmienił je, ale także dlatego, że był błędny. Na przykład po awarii / ponownym uruchomieniu Firefoksa widziałem osierocone okna (jak sądzę z wtyczki flash) ze _NET_WM_PID
wskazaniem na proces, który zmarł dawno temu.
Alternatywnym sposobem jest uruchomienie
xwininfo -root -tree
i sprawdź właściwości rodziców danego okna. To może dać ci kilka wskazówek na temat pochodzenia okna.
Ale! Chociaż możesz nie znaleźć procesu, który utworzył to okno, wciąż istnieje sposób, aby dowiedzieć się, skąd ten proces połączył się z serwerem X. I tak jest dla prawdziwych hakerów. :)
Identyfikator okna 0x1600045, który znasz z zerowanymi niższymi bitami (tj. 0x1600000), jest „bazą klienta”. Wszystkie identyfikatory zasobów przydzielone temu klientowi są „oparte” na nim (0x1600001, 0x1600002, 0x1600003 itp.). Serwer X przechowuje informacje o swoich klientach w tablicy klientów [], a dla każdego klienta jego „baza” jest przechowywana w klientach [i] -> zmienna clientAsMask. Aby znaleźć gniazdo X odpowiadające temu klientowi, musisz podłączyć się do serwera X za pomocą gdb
, przejść przez tablicę klientów [], znaleźć klienta z tym clientAsMask
i wydrukować jego deskryptor gniazda, zapisany w ((OsCommPtr) (klienci [i] - > osPrivate)) -> fd.
Może być podłączonych wiele klientów X, więc aby nie sprawdzać ich wszystkich ręcznie, użyjmy funkcji 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
Po znalezieniu gniazda możesz sprawdzić, kto jest z nim połączony, a na końcu znaleźć proces.
OSTRZEŻENIE : NIE podłączaj gdb do X-serwera od WEWNĄTRZ X-serwera. gdb zawiesza proces, do którego się dołącza, więc jeśli podłączysz się do niego z poziomu sesji X, zamrozisz swój serwer X i nie będziesz mógł wchodzić w interakcje z gdb. Musisz albo przełączyć się na terminal tekstowy ( Ctrl+Alt+F2
), albo połączyć się z komputerem przez ssh.
Przykład:
Znajdź PID swojego X-serwera:
$ ps ax | grep X
1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
Identyfikator okna to 0x1600045, więc podstawa klienta to 0x1600000. Podłącz do serwera X i znajdź deskryptor gniazda klienta dla tej bazy klientów. Musisz zainstalować informacje debugowania dla X-serwera (pakiet -debuginfo dla dystrybucji rpm-lub pakiet -dbg dla deba).
$ 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
Teraz wiesz, że klient jest podłączony do gniazda 31 serwera. Użyj, lsof
aby znaleźć to, co to gniazdo:
$ sudo lsof -n | grep 1237 | grep 31
X 1237 root 31u unix 0xffff810008339340 8512422 socket
(tutaj „X” to nazwa procesu, „1237” to jego pid, „root” to użytkownik, z którego działa, „31u” to deskryptor gniazda)
Tam możesz zobaczyć, że klient jest połączony przez TCP, następnie możesz przejść do komputera, z którego jest podłączony i sprawdzić netstat -nap
tam, aby znaleźć proces. Ale najprawdopodobniej zobaczysz tam gniazdo unix, jak pokazano powyżej, co oznacza, że jest to klient lokalny.
Aby znaleźć parę dla tego gniazda uniksowego, możesz użyć techniki MvG
(będziesz również potrzebować informacji o debugowaniu dla zainstalowanego jądra):
$ sudo gdb -c /proc/kcore
(gdb) print ((struct unix_sock*)0xffff810008339340)->peer
$1 = (struct sock *) 0xffff810008339600
(gdb) quit
Teraz, gdy znasz już gniazdo klienta, użyj lsof
PID , aby je zatrzymać:
$ sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
Otóż to. Proces utrzymywania tego okna to „firefox” o identyfikatorze procesu 7725
Edycja 2017 : Teraz jest więcej opcji, jak widać na Kto ma drugi koniec tej pary gniazd unixowych? . W Linuksie 3.3 lub nowszym oraz w wersji lsof
4.89 lub nowszej możesz zastąpić punkty 3 do 5 powyżej:
lsof +E -a -p 1237 -d 31
aby dowiedzieć się, kto jest na drugim końcu gniazda na fd 31 procesu X-server o identyfikatorze 1237.