Mogę powiedzieć, dlaczego zawodzi, chociaż tak naprawdę nie wiem, która część systemu jest odpowiedzialna. Chociaż .dtors
jest zapisany w pliku binarnym, wygląda na to, że (wraz z .ctors
GOT i kilkoma innymi rzeczami) jest mapowany na osobną, nie zapisywalną stronę w pamięci. W moim systemie .dtors
ustawia się na 0x8049f14
:
$ readelf -S test
[17] .ctors PROGBITS 08049f0c 000f0c 000008 00 WA 0 0 4
[18] .dtors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
[19] .jcr PROGBITS 08049f1c 000f1c 000004 00 WA 0 0 4
[20] .dynamic DYNAMIC 08049f20 000f20 0000d0 08 WA 6 0 4
[21] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4
[22] .got.plt PROGBITS 08049ff4 000ff4 00001c 04 WA 0 0 4
[23] .data PROGBITS 0804a010 001010 000008 00 WA 0 0 4
[24] .bss NOBITS 0804a018 001018 000008 00 WA 0 0 4
Jeśli uruchomię plik wykonywalny i sprawdzę /proc/PID/maps
, zobaczę:
08048000-08049000 r-xp 00000000 08:02 163678 /tmp/test
08049000-0804a000 r--p 00000000 08:02 163678 /tmp/test
0804a000-0804b000 rw-p 00001000 08:02 163678 /tmp/test
.data
/ .bss
są nadal zapisywalne na własnej stronie, ale inni na 0x8049000-0x804a000
nich nie. Zakładam, że jest to funkcja bezpieczeństwa w jądrze (jak powiedziałeś: „nastąpił ruch w kierunku readonly .dtors, plt, ostatnio”), ale nie wiem dokładnie, jak się nazywa (OpenBSD ma coś bardzo podobnego o nazwie W ^ X ; Linux ma PaX , ale nie jest wbudowany w większość jąder)
Możesz obejść to za pomocą mprotect
, co pozwala zmienić atrybuty strony w pamięci:
mprotect((void*)0x8049000, 4096, PROT_WRITE);
Dzięki temu mój program testowy nie ulega awarii, ale jeśli spróbuję zastąpić końcową wartę .dtors
( 0x8049f18
) adresem innej funkcji, funkcja ta nadal się nie uruchamia; tej części, której nie mogę zrozumieć.
Mam nadzieję, że ktoś inny wie, co jest odpowiedzialne za wykonanie strony tylko do odczytu i dlaczego modyfikowanie .dtors
wydaje się nie robić nic w moim systemie