core(5) File Formats Manual core(5) NAZWA core - plik zrzutu pamieci OPIS Dla pewnych sygnalow domyslna akcja procesu jest zakonczenie dzialania i utworzenie pliku zrzutu pamieci (core), czyli pliku zawierajacego obraz pamieci procesu w czasie, gdy zostal on zakonczony. Dowolny debugger (np. gdb(1)) moze uzyc tego obrazu do zbadania stanu programu w czasie jego zakonczenia. Liste sygnalow powodujacych utworzenie pliku core przez proces mozna znalezc w signal(7). Proces moze ustawic miekki limit zasobow RLIMIT_CORE, aby ograniczyc maksymalny rozmiar pliku, ktory zostanie utworzony po otrzymaniu sygnalu powodujacego zrzut pamieci; szczegolowe informacje mozna znalezc w getrlimit(2). W nastepujacych wypadkach plik zrzutu pamieci nie bedzie utworzony: o Proces nie ma uprawnien, aby zapisac plik zrzutu pamieci (Domyslnie plik ten nazywa sie core lub core.pid, gdzie pid jest identyfikatorem procesu ktory zrzuca pamiec i jest tworzony w biezacym katalogu roboczym procesu. Nazwe te mozna zmienic - patrz nizej). Zapisywanie pliku zrzutu nie powiedzie sie rowniez wtedy, gdy prawa katalogu, w ktorym ten plik mialby byc utworzony, nie pozwalaja na zapis do niego lub gdy plik o tej samej nazwie istnieje i nie jest zapisywalny lub nie jest zwyklym plikiem (ale np. katalogiem lub dowiazaniem symbolicznym). o Juz istnieje (zapisywalny, zwykly) plik o tej samej nazwie, jaka zostalaby uzyta dla pliku zrzutu pamieci, jednakze plik ten ma wiecej niz jedno dowiazanie twarde. o System plikow, w ktorym zostalby utworzony plik zrzutu pamieci, jest pelny, wyczerpal mu sie limit i-wezlow, jest zamontowany w trybie tylko do odczytu albo uzytkownik osiagnal przydzial systemu plikow. o Nie istnieje katalog, w ktorym mialby byc utworzony plik zrzutu pamieci. o Limity zasobow RLIMIT_CORE (rozmiar pliku zrzutu pamieci) lub RLIMIT_FSIZE (rozmiar pliku) dla procesu sa ustawione na zero; patrz getrlimit(2) i dokumentacja wbudowanego w powloke polecenia ulimit (lub limit w powloce csh(1)). RLIMIT_CORE bedzie ignorowane, gdy system skonfigurowano do przekazywania zrzutow pamieci za pomoca potoku do programu. o Wykonywany przez proces plik binarny nie ma wlaczonych uprawnien do odczytu (jest to zabezpieczenie, w celu wykluczenia sytuacji, gdy plik wykonywany, ktorego odczyt jest niemozliwy, tworzylby -- potencjalnie odczytywalny -- zrzut pamieci zawierajacy obraz pliku wykonywalnego). o Proces uruchomil program z flaga set-user-ID (set-group-ID), ktorego wlascicielem jest uzytkownik (grupa) inny niz rzeczywisty uzytkownik (grupa) procesu lub proces wykonujacy program ma przywileje plikowe (zob. capabilities(7)). (Jednakze patrz w prctl(2) opis operacji PR_SET_DUMPABLE oraz w proc(5) opis pliku /proc/sys/fs/suid_dumpable). o /proc/sys/kernel/core_pattern jest pusty i /proc/sys/kernel/core_uses_pid zawiera wartosc 0 (pliki te opisano ponizej). Prosze zauwazyc, ze gdy /proc/sys/kernel/core_pattern jest pusty i /proc/sys/kernel/core_uses_pid zawiera wartosc 1, to pliki zrzutu pamieci beda mialy nazwy w postaci .pid, a pliki takie sa ukryte, chyba ze poda sie opcje ls(1) -a. o (od Linuksa 3.7) Jadro zostalo zbudowane bez opcji CONFIG_COREDUMP. Dodatkowo zrzut pamieci moze nie zawierac czesci przestrzeni adresowej procesu jesli uzyto flagi MADV_DONTDUMP madvise(2). W systemach korzystajacym z systemd(1) jako init, pliki zrzutu pamieci moga byc w zamian umieszczane w polozeniu wskazanym przez systemd(1). Wiecej szczegolow ponizej. Nazwy plikow zrzutu pamieci Domyslnie plik zrzutu pamieci nazywa sie core, jednakze w pliku /proc/sys/kernel/core_pattern (od wersji 2.6 i 2.4.21 Linuksa) mozna zdefiniowac szablon, ktory bedzie uzyty do nazywania plikow zrzutu pamieci. Szablon ten moze zawierac specjalne znaczniki zaczynajace sie od ,,%", ktore podczas tworzenia pliku zrzutu beda zastapione nastepujacymi wartosciami: %% Pojedynczy znak %. %c Miekki limit zasobu rozmiaru pliku zrzutu pamieci procesu zrzucajacego pamiec (od Linuksa 2.6.24). %d Tryb zrzutu -- taki sam jak wartosc zwracana przez prctl(2) PR_GET_DUMPABLE (od Linuksa 3.7). %e Wartosc comm procesu lub watku, zwykle rowna nazwie pliku wykonywalnego (bez przedrostka sciezki i obcieta do maksymalnie 15 znakow), lecz mogaca byc rowniez zmodyfikowana na inna wartosc, zob. opis /proc/pid/comm i /proc/pid/task/tid/comm w proc(5). %E Nazwa sciezki pliku wykonywalnego, z ukosnikami (,,/") zastapionymi przez wykrzykniki (,,!") (od Linuksa 3.0). %g Numeryczny identyfikator grupy (GID) procesu, ktory zrzucil pamiec. %h Nazwa komputera (taka sama jak nodename zwracane przez uname(2)). %i identyfikator watku (TID) ktory zainicjowal zrzut pamieci, taki jak w przestrzeni nazw PID-ow w ktorej watek dziala (od Linuksa 3.18). %I identyfikator watku (TID) ktory zainicjowal zrzut pamieci, taki jak w poczatkowej przestrzeni nazw PID-ow (od Linuksa 3.18). %p identyfikator zrzucanego procesu, taki jak w przestrzeni nazw PID-ow w ktorej proces dziala. %P identyfikator zrzucanego procesu, taki jak w poczatkowej przestrzeni nazw PID-ow (od Linuksa 3.12). %s Numer sygnalu powodujacego zrzut pamieci. %t Czas zrzutu wyrazony w sekundach od poczatku epoki, czyli od 1970-01-01 00:00:00 +0000 (UTC). %u Numeryczny identyfikator uzytkownika (UID) procesu, ktory zrzucil pamiec. Jesli szablon konczy sie pojedynczym znakiem %, to znak ten zostanie usuniety z nazwy pliku zrzutu. Podobnie zostana usuniete wszelkie kombinacje % ze znakami innymi niz te, wymienione powyzej. Wszystkie inne znaki szablonu stana sie czescia nazwy pliku zrzutu. Szablon moze zawierac znaki ,,/", ktore sa interpretowane jako separatory nazw katalogow. Maksymalna dlugosc wygenerowanej nazwy pliku wynosi 128 bajtow (64 bajty w wersjach wczesniejszych niz Linux 2.6.19). Domyslna wartoscia jest ,,core". W celu zachowania wstecznej zgodnosci, jesli /proc/sys/kernel/core_pattern nie zawiera %p, a /proc/sys/kernel/core_uses_pid (patrz nizej) ma niezerowa wartosc, to .PID bedzie dolaczony do nazwy pliku zrzutu. Sciezki sa interpretowane zgodnie z ustawieniami aktywnymi dla zalamujacego sie procesu. Oznacza to: przestrzen nazw montowania (zob. mount_namespaces(7)), jego biezacy katalog roboczy (odnaleziony za pomoca getcwd(2)) oraz jego katalog glowny (zob. chroot(2)). Od Linuksa 2.4, Linux dostarcza rowniez bardziej prymitywna metode kontrolowania nazwy pliku zrzutu pamieci. Gdy plik /proc/sys/kernel/core_uses_pid zawiera wartosc 0, plik zrzutu pamieci ma po prostu nazwe core. Gdy plik ten zawiera wartosc niezerowa, plik zrzutu pamieci bedzie zawieral w swojej nazwie ID procesu, w postaci core.PID. Od Linuksa 3.6 jesli /proc/sys/fs/suid_dumpable ustawiono na 2 (,,suidsafe") to wzorzec musi byc albo sciezka absolutna (zaczynajaca sie znakiem ,,/") lub potokiem, zgodnie z ponizsza definicja. Przekazywanie zrzutow pamieci potokiem do programu Od wersji Linuksa 2.6.19, Linux obsluguje alternatywna skladnie pliku /proc/sys/kernel/core_pattern. Jesli pierwszym znakiem pliki jest symbol potoku (|), to wszystko, co po nim wystepuje, jest interpretowane jako wiersz polecenia dla programu w przestrzeni uzytkownika (lub skryptu), ktory ma byc wykonany. Od Linuksa 5.3.0, szablon potoku jest dzielony na spacjach na liste argumentow przed rozwinieciem parametrow szablonu. We wczesniejszych jadrach parametry szablonu byly najpierw rozwijane, a wynikowy lancuch byl dzielony na spacjach na liste argumentow. Oznacza to, ze we wczesniejszych jadrach, nazwy plikow wykonywalnych dodawane za pomoca parametrow szablonu %e i %E mogly ulec podzieleniu na wiele argumentow. Procedura obslugi zrzutu pamieci musi zatem umieszczac nazwy plikow wykonywalnych jako ostatni argument i upewnic sie, ze polaczy wszystkie skladowe nazwy pliku wykonywalnego uzywajacego spacji. Nazwy plikow wykonywalnych zawierajace wiele spacji nie byly prawidlowo reprezentowane we wczesniejszych jadrach, co oznacza, ze procedura obslugi zrzutu pamieci musi uzywac mechanizmow do odnalezienia nazwy pliku wykonywalnego. Zamiast zostac zapisanym na dysku, zrzut pamieci jest przekazywany na standardowe wejscie programu. Prosze zauwazyc, ze: o Program musi byc podany uzywajac sciezki bezwzglednej (lub sciezki wzglednej w stosunku do korzenia systemu plikow, czyli katalogu /) i musi wystepowac bezposrednio po znaku ,,|". o Argumenty linii polecen moga zawierac dowolne z wymienionych powyzej specyfikatorow %. Na przyklad, aby przekazac identyfikator procesu zrzucajacego pamiec, nalezy podac %p jako argument. o Proces tworzony do wykonania programu jest wykonywany jako uzytkownik i grupa root. o Uruchomienie jako root nie pomija w zaden sposob procedur bezpieczenstwa. Przede wszystkim, LSM-y (np. SELinux) sa wciaz aktywne i moga zapobiec uzyskaniu szczegolow poprzez /proc/pid, przez procedure obslugi, na temat zalamanego procesu. o Sciezka programu jest interpretowana zgodnie z poczatkowa przestrzenia nazw montowan, jako ze zawsze jest on tu wykonywany. Nie maja na nia wplywu ustawienia (np. katalog glowny, przestrzen nazw montowan, biezacy katalog roboczy) zalamujacego sie procesu. o Proces dziala w swoich pierwotnych przestrzeniach nazw (PID, montowania, uzytkownika itd.), a nie w przestrzeniach nazw zalamujacego sie procesu. Mozna uzyc znacznikow, takich jak %P, aby odnalezc wlasciwy katalog /proc/pid i sprawdzic/wejsc w przestrzenie nazw zalamujacego sie procesu, jesli jest taka potrzeba. o Proces uruchamia sie ze swoim biezacym katalogiem roboczym jako katalogiem glownym. Jesli to wskazane, mozna zmienic katalog roboczy zrzucanego procesu za pomoca wartosci podanej przez znacznik %P, aby zmienic polozenie zrzucanego procesu za pomoca /proc/pid/cwd. o Mozna przekazac do programu argumenty linii polecen (od Linuksa 2.6.24), rozdzielajac je spacjami (az do wyczerpania limitu calkowitej dlugosci linii wynoszacego 128 bajtow). o Limit RLIMIT_CORE nie jest pilnowany w przypadku zrzutow pamieci, ktore sa przekazywane potokiem za pomoca tego mechanizmu. /proc/sys/kernel/core_pipe_limit Przy zbieraniu zrzutow pamieci za pomoca potoku do program w przestrzeni uzytkownika, moze okazac sie przydatne zbieranie danych o zalamujacym sie procesie z katalogu /proc/pid procesu. Aby uczynic to bezpiecznie, jadro musi zaczekac na wyjscie przez program zbierajacy zrzut pamieci, aby nie usuwac przedwczesnie plikow /proc/pid zalamujacego sie procesu. Z drugiej jednak strony, daje to mozliwosc blokowania dorzynania (ang. reaping) zalamanego procesu, przez niepoprawnie dzialajacy program zbierajacy, ktory moze nigdy nie wyjsc. Od Linuksa 2.6.32, mozna uzyc /proc/sys/kernel/core_pipe_limit do obrony przed taka ewentualnoscia. Wartosc pliku definiuje, jak wiele wspolbieznych zalamujacych sie procesow mozna przekazac rownolegle, potokiem, do programow w przestrzeni uzytkownika. Po przekroczeniu tej wartosci, zalamujace sie programy niemieszczace sie w tej wartosci sa odnotowywane w dzienniku jadra, a ich zrzuty pamieci sa pomijane. Wartosc 0 w tym pliku ma specjalne znaczenie. Oznacza, ze rownolegle moze byc przechwytywana nieograniczona liczba procesow, ale nie zajdzie zadne oczekiwanie (tj. program zbierajacy nie ma gwarancji dostepu do /proc/). Domyslna wartoscia pliku jest 0. Kontrolowanie mapowan zapisywanych do pliku zrzutu pamieci Od Linuksa 2.6.23, mozna uzyc specyficznego dla Linuksa pliku /proc/PID/coredump_filter do kontrolowania, ktore segmenty pamieci zostana zapisane do pliku zrzutu pamieci, w przypadku gdy pamiec jest zrzucana przez proces o podanym identyfikatorze. Wartosc w tym pliku jest maska bitowa typow mapowan pamieci (patrz mmap(2)). Jesli bit jest ustawiony w masce, to odpowiadajace mu mapowanie jest zapisywane w pliku, w przeciwnym wypadku - nie jest. Bity w masce maja nastepujace znaczenia: bit 0 Zrzucanie anonimowych mapowan prywatnych. bit 1 Zrzucanie anonimowych mapowan wspoldzielonych. bit 2 Zrzucanie prywatnych mapowan plikow. bit 3 Zrzucanie wspoldzielonych mapowan plikow. bit 4 (od Linuksa 2.6.24) Zrzucanie naglowkow ELF. bit 5 (od Linuksa 2.6.28) Zrzucanie prywatnych duzych stron. bit 6 (od Linuksa 2.6.28) Zrzucanie wspoldzielonych duzych stron. bit 7 (od Linuksa 4.4) Zrzucanie prywatnych stron DAX. bit 8 (od Linuksa 4.4) Zrzucanie wspoldzielonych stron DAX. Domyslnie ustawione sa nastepujace bity: 0, 1, 4 (jesli jest wlaczona opcja CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS konfiguracji jadra) oraz 5. Te wartosc domyslna mozna zmodyfikowac przy rozruchu za pomoca opcji coredump_filter. Wartosc tego pliku jest wyswietlana szesnastkowo (z tego powodu domyslna wartosc jest wyswietlana jako 33). Strony wejscia/wyjscia mapowane w pamieci, takie jak bufor ramki, nigdy nie sa zrzucane, a wirtualne strony DSO (vdso(7)) sa zawsze zrzucane, niezaleznie od wartosci coredump_filter. Proces-dziecko utworzony przez fork(2) dziedziczy wartosc coredump_filter od swojego rodzica; wartosc ta jest takze zachowywana podczas execve(2). Moze byc uzyteczne ustawienie coredump_filter w powloce przed uruchomieniem programu, na przyklad: $ echo 0x7 > /proc/self/coredump_filter $ ./some_program Plik istnieje, jesli jadro zostalo zbudowane z wlaczona opcja konfiguracji CONFIG_ELF_CORE. Zrzuty pamieci i systemd W systemach korzystajacych z init w postaci systemd(1), zrzuty pamieci moga byc umieszczane w polozeniu okreslanym przez systemd(1). systemd(1) uzywa do tego funkcji core_pattern, ktora pozwala na przekazywanie potokiem zrzutow pamieci do programu. Mozna to zweryfikowac, sprawdzajac czy zrzuty pamieci sa przekazywane potokiem do programu systemd-coredump(8): $ cat /proc/sys/kernel/core_pattern |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e W tym przypadku, zrzuty pamieci beda umieszczane w polozeniu skonfigurowanym dla systemd-coredump(8), zwykle jako pliki skompresowane lz4(1), w katalogu /var/lib/systemd/coredump/. Mozna wypisac liste zarejestrowanych przez systemd-coredump(8) zrzutow pamieci za pomoca coredumpctl(1): $ coredumpctl list | tail -5 Wed 2017-10-11 22:25:30 CEST 2748 1000 1000 3 present /usr/bin/sleep Thu 2017-10-12 06:29:10 CEST 2716 1000 1000 3 present /usr/bin/sleep Thu 2017-10-12 06:30:50 CEST 2767 1000 1000 3 present /usr/bin/sleep Thu 2017-10-12 06:37:40 CEST 2918 1000 1000 3 present /usr/bin/cat Thu 2017-10-12 08:13:07 CEST 2955 1000 1000 3 present /usr/bin/cat Informacje pokazywane dla kazdego zrzutu pamieci obejmuja date i czas zrzutu, identyfikatory: procesu, uzytkownika i grupy zrzucajacego procesu, numer sygnalu powodujacego zrzut i sciezka do pliku wykonywalnego, ktory byl uruchomiony przez zrzucany proces. Mozna podac do coredumpctl(1) wiele opcji, ktore pozwalaja wskazac plik zrzutu pamieci, ktory ma byc wyciagniety z lokalizacji systemd(1) do okreslonego pliku. Na przyklad, aby wydobyc zrzut pamieci dla procesu o PID 2955 pokazanego powyzej, do pliku nazwanego core w biezacym katalogu mozna uzyc polecenia: $ coredumpctl dump 2955 -o core Wiecej szczegolow znajduje sie w podreczniku systemowym coredumpctl(1). Aby (na stale) wylaczyc mechanizm systemd(1) archiwizujacy zrzuty pamieci, przywracajac bardziej tradycyjne zachowanie linuksowe, mozna przeslonic mechanizm systemd(1), za pomoca konstrukcji podobnej do ponizej: # echo "kernel.core_pattern=core.%p" > \ /etc/sysctl.d/50-coredump.conf # /lib/systemd/systemd-sysctl Mozna rowniez tymczasowo (do nastepnego przeladowania systemu) zmienic ustawienie core_pattern poleceniem podobnym do ponizszego (ktore powoduje wlaczenie do nazw zrzutu pamieci rowniez nazwy pliku wykonywalnego i numer sygnalu wyzwalajace zrzut pamieci): # sysctl -w kernel.core_pattern="%e-%s.core" UWAGI Aby uzyskac zrzut pamieci dzialajacego procesu, mozna uzyc polecenia gcore programu gdb(1). W wersjach jadra Linux do 2.6.27 wlacznie, jezeli pamiec zrzuca proces wielowatkowy (albo - bardziej precyzyjnie - proces, ktory dzieli swa pamiec z innym procesem utworzonym z flaga CLONE_VM funkcji clone(2)), to identyfikator procesu zawsze bedzie dolaczony do nazwy pliku zrzutu, chyba ze ow identyfikator procesu juz wystepuje w nazwie pliku, poniewaz w pliku /proc/sys/kernel/core_pattern uzyto specyfikatora p (Jest to szczegolnie uzyteczne podczas stosowania przestarzalej implementacji LinuxThreads, w ktorej kazdy watek procesu ma inny PID). PRZYKLADY Ponizszy program pokazuje uzycie skladni potoku w pliku /proc/sys/kernel/core_pattern. Ponizsza sesja powloki demonstruje uzycie tego programu (skompilowanego do pliku o nazwie core_pattern_pipe_test): $ cc -o core_pattern_pipe_test core_pattern_pipe_test.c $ su Haslo: # echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \ /proc/sys/kernel/core_pattern # exit $ sleep 100 ^\ # wpisz control+odwrotny ukosnik Quit (core dumped) $ cat core.info argc=5 argc[0]= argc[1]=<20575> argc[2]= argc[3]= argc[4]= Calkowita liczba bajtow pliku core: 282624 Kod zrodlowy programu /* core_pattern_pipe_test.c */ #define _GNU_SOURCE #include #include #include #include #include #include #define BUF_SIZE 1024 int main(int argc, char *argv[]) { ssize_t nread, tot; char buf[BUF_SIZE]; FILE *fp; char cwd[PATH_MAX]; /* Zmienia biezacy katalog roboczy na katalog procesu ktory generuje zrzut pamieci. */ snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]); chdir(cwd); /* Zapisuje wyjscie do pliku "core.info" w tym katalogu. */ fp = fopen("core.info", "w+"); if (fp == NULL) exit(EXIT_FAILURE); /* Wyswietla argumenty wiersza polecen przekazane do programu filtrujacego "core_pattern". */ fprintf(fp, "argc=%d\n", argc); for (size_t j = 0; j < argc; j++) fprintf(fp, "argc[%zu]=<%s>\n", j, argv[j]); /* Zlicza bajty na standardowym wejsciu (daje rozmiar zrzutu pamieci). */ tot = 0; while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0) tot += nread; fprintf(fp, "Calkowita liczba bajtow pliku core: %zd\n", tot); fclose(fp); exit(EXIT_SUCCESS); } ZOBACZ TAKZE bash(1), coredumpctl(1), gdb(1), getrlimit(2), mmap(2), prctl(2), sigaction(2), elf(5), proc(5), pthreads(7), signal(7), systemd-coredump(8) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Robert Luberda i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.06 31 pazdziernika 2023 r. core(5)