sub rsp, <size>
abyste si rezervovali místo v zásobníku, než se ho dotknete, pokud používáte více než 128 bajtů pod RSP.
Když dojde k chybě, podívejte se na mapu paměti procesu. Možná používáte paměť tak hluboko pod RSP, že jádro nezvyšuje mapování zásobníku, a proto je to jen obyčejný přístup k nenamapované stránce =neplatná chyba stránky => jádro poskytuje SIGSEGV.
(ABI definuje pouze 128bajtovou červenou zónu, ale v praxi jediná věc, která může blokovat tuto paměť, je obslužný program signálu (který jste nenainstalovali) nebo GDB se systémem print some_func()
pomocí zásobníku vašeho programu k volání funkce ve vašem programu.)
Normálně je Linux docela ochotný rozšířit mapování zásobníku, aniž by se dotýkal mezilehlých stránek, ale zjevně kontroluje hodnotu RSP. Normálně přesouváte RSP místo pouhého používání paměti hluboko pod ukazatel zásobníku (protože neexistuje žádná záruka, že je to bezpečné). Viz Jak je alokována paměť zásobníku při použití instrukcí x86 „push“ nebo „sub“?
Další duplikát:Kterou výjimku lze vygenerovat při odečítání registru ESP nebo RSP? (rostoucí zásobník), kde se používá sub rsp, 5555555
předtím, než se dotknete nového zásobníku, byla dostatečná paměť.
Stack ASLR může spustit RSP na různých místech vzhledem k hranici stránky , takže vám to někdy může jen stěží uniknout. Linux zpočátku mapuje 132 kB prostoru zásobníku , a to zahrnuje prostor pro prostředí a argumenty na zásobníku při vstupu do _start
. Tvých 128 kB je tomu velmi blízko, takže je zcela pravděpodobné, že to někdy funguje náhodně.
A BTW, neexistuje žádný důvod, proč skutečně kopírovat paměť v uživatelském prostoru, zvláště ne 1 bajt najednou. Stačí předat stejnou adresu do write
.
Nebo alespoň filtrujte na místě, je-li to možné, takže vaše vyrovnávací paměť bude menší.
Také normální způsob načtení bajtu je movzx eax, byte [mem]
. Používejte pouze mov al, [mem]
pokud konkrétně chcete sloučit se starou hodnotou RAX. U některých procesorů mov
na al
má falešnou závislost na staré hodnotě, kterou můžete přerušit zápisem celého registru.
A BTW, pokud váš program vždy používá tento prostor, můžete jej také staticky alokovat v BSS. To umožňuje efektivnější indexované adresování, pokud se rozhodnete sestavit spustitelný soubor závislý na poloze (bez PIE).
Červená zóna v amd64 je dlouhá pouze 128 bajtů, ale používáte 131072 bajtů pod RSP. Posuňte ukazatel zásobníku dolů, aby zahrnoval vyrovnávací paměti, které chcete uložit do zásobníku.