Um estouro de pilha é detectado por hardware ou software?

26

É tarefa do software (sistema operacional) detectar estouros de pilha ou é detectado um estouro de pilha no hardware, causando uma exceção na CPU?

gilianzz
fonte
Eu diria hardware, através de falhas de MMU na maioria das CPUs. O x86 no modo de 32 bits tinha segmentação além da paginação, e o "Segmento de pilha" está associado, como os segmentos Código, Dados, Ext ... com um endereço base e um tamanho. Qualquer acesso fora desse intervalo provocaria uma falha.
TEMLIB 22/02

Respostas:

25

Pode ser software ou hardware, ou ambos, ou nenhum.

Existem dois tipos de estouro: estouro ao aumentar a pilha (ao inserir uma função) e estouro ao acessar uma matriz na pilha. Estouros ao aumentar a pilha podem ser detectados fazendo uma verificação de limites na entrada da função, para verificar se há espaço suficiente (e sinalizar um erro ou aumentar a pilha, se não houver). Estouros ao acessar uma matriz na pilha são apenas um problema em idiomas de baixo nível que não verificam os limites da matriz; a solução existe para verificar os limites da matriz.

Essas abordagens de software têm a vantagem de funcionar de maneira totalmente confiável: você pode ter certeza de que qualquer excesso de pilha será detectado. A desvantagem é que eles aumentam o tamanho do código e o tempo de execução. O hardware pode ajudar, fornecendo um método para detectar a maioria dos transbordamentos sem nenhum custo, desde que não ocorra transbordamento. Em uma arquitetura com uma MMU ¹, o ambiente de tempo de execução pode organizar o mapeamento da pilha em um limite de página, com a próxima página permanecendo não mapeada.

+---------------+---------------+---------------+---------------+
| stack                         | unmapped      | other stuff   |
|    ----> direction of growth  |               |               |
+---------------+---------------+---------------+---------------+
^               ^               ^               ^               ^  page boundaries

Dessa forma, se o software tentar acessar dados além do limite da página (seja porque o ponteiro da pilha foi além do limite ou porque o acesso à matriz está fora dos limites e além do limite), ele causará uma falha ao acessar uma área não mapeada . Isso só acontece se o excesso for pequeno o suficiente: se a quantidade de excesso for muito grande, o programa pode acabar acessando outras coisas do outro lado da lacuna no espaço de endereço.

A desvantagem da abordagem de hardware é que ela não é totalmente confiável, pois um excesso de quantidade pode não ser detectado e que não detecta estouros de matriz que permanecem no espaço endereçável.

Para detectar estouros de matriz, outra técnica de software é um canário : coloque um valor especial no topo da pilha ou entre os quadros e verifique se o valor do canário não mudou no retorno da função. Essa também é uma técnica imperfeita, pois o excesso pode evitar o canário por completo ou pode não ser detectado porque o valor do canário foi restaurado no momento em que é verificado. No entanto, é útil dificultar a exploração de algumas vulnerabilidades de segurança.

A maneira mais segura e barata de evitar estouros de pilha é calcular a quantidade de pilha que o programa precisará antes de começar a executá-la, por análise estática. No entanto, isso nem sempre é prático: a quantidade de pilha necessária para um programa é indecidível em geral e depende dos dados que são manipulados pelo programa.

¹ O mesmo princípio também pode ser aplicado com apenas uma MPU, ou sem proteção de memória, se houver um único encadeamento cuja pilha esteja na borda dos mapeamentos físicos existentes.

Gilles 'SO- parar de ser mau'
fonte
4
Eu não chamaria acesso de matriz fora dos limites a um estouro de pilha, mesmo que a matriz estivesse na pilha. É apenas um caso especial de estouro de buffer.
CodesInChaos
Não alocar para os itens principais da pilha que são referenciados em relação a um ponteiro que não seja de pilha / quadro ou deslocamento não constante evitaria o excesso de pilha tradicional. O uso de uma pilha de endereços de retorno separada (ou pilha de derramamento de registros / RA como Itanium) reduziria pelo menos significativamente as oportunidades de programação orientada a retornos.
Paul A. Clayton
O acesso fora dos limites é mais adequadamente chamado de excedente , não de excedente.
Ben Voigt
3
@ awesomebing1 nem toda plataforma detecta estouros de pilha. Você pode simplesmente substituir o que estiver após a pilha (semelhante a qualquer outro estouro de buffer).
user253751
11
@CodesInChaos, às vezes o estouro de buffer nos buffers alocados à pilha é chamado de "estouro de pilha" (abreviado). É verdade que essa terminologia pode ser um pouco confusa sem contexto.
DW