Este é um acompanhamento de Como funciona a inspeção de pilha? que explora a noção em mais detalhes
A inspeção de pilha é um mecanismo para garantir a segurança no contexto das máquinas virtuais JVM e CLR quando módulos de código baixados externamente de diferentes níveis de confiança podem estar em execução juntos. As bibliotecas do sistema precisam de alguma maneira de distinguir entre chamadas originadas em código não confiável e chamadas originadas do próprio aplicativo confiável. Isso é feito associando ao código o principal correspondente à sua origem. Em seguida, as permissões de acesso são registradas na pilha e sempre que uma chamada para um método sensível do sistema é feita, a pilha é percorrida para verificar se as permissões apropriadas para o principal que faz a chamada estão presentes na pilha.
Quais são as limitações da inspeção de pilha? Quais mecanismos foram propostos para substituí-lo? Alguma mudança significativa foi feita no modelo desde que foi introduzido no final dos anos 90?
fonte
Respostas:
A inspeção de pilha é necessária porque os programas na JVM e CLR têm acesso padrão a operações perigosas; portanto, algo deve ser feito para evitar desastres. Por exemplo, um programa não confiável pode fazer referência a uma biblioteca de E / S e chamá-la:
Portanto, em cada operação perigosa feita, precisamos verificar se é permitida. Com a inspeção de pilha, geralmente é complicado entender quem tem acesso a quê. Também dificulta otimizações como inlining e tail calls.
Um mecanismo superior é não dar a cada programa acesso automático a operações perigosas em primeiro lugar. Nesse modelo, não há como importar uma biblioteca de E / S. A única maneira de obter acesso a uma biblioteca de E / S é se alguém lhe der. Isso é chamado de segurança de capacidade. Uma introdução pode ser encontrada aqui .
Em vez disso, escreveríamos o programa anterior como este:
A biblioteca IO é um parâmetro para o ponto de entrada do programa, e isso é chamado de recurso (porque fornece algum recurso, nesse caso, para executar IO). Para poder executar este programa, precisamos ter acesso a um recurso de E / S e executar o programa chamando
Main(ourIOlibrary)
. Se estamos executando um programa não confiável, simplesmente não passamos nossa biblioteca de E / S para ele, pois ele pode usar essa biblioteca para excluir nossos arquivos. Em alguns casos, queremos dar a um programa não confiável acesso limitado ao sistema de arquivos. Nesse caso, criamos um wrapper em torno de nossa própria biblioteca de E / S que permite apenas o acesso a um determinado diretório e passamos esse para o programa não confiável, em vez da biblioteca de E / S completaPortanto, se precisarmos de um recurso de E / S para chamar um programa que precise de um recurso de E / S, isso também significa que tudo o que invocou nosso programa precisava ter acesso a um recurso de E / S para poder fornecê-lo. Então, de onde veio sua capacidade de IO? Bem, eventualmente, há um ponto em que o ser humano que opera o computador invocou um programa. Esse humano tem acesso a todos os recursos do sistema e, portanto, conseguiu passar o recurso de E / S. Se esse humano não confiar no programa que está executando, ele simplesmente não passará sua capacidade de IO para ele.
Provavelmente, você pode imaginar facilmente outros tipos de recursos: acesso à Internet, acesso para desenhar coisas na tela etc. Por exemplo, um sistema seguro de plug-in de navegador pode fornecer recursos gráficos a um plug-in não confiável que permite apenas pintar gráficos em um retângulo predefinido na página.
fonte
Uma limitação da inspeção de pilha, conforme tradicionalmente implementada, é que ela interrompe as chamadas de cauda apropriadas. Em particular, implementações típicas precisam manter toda a "pilha" sempre disponível. Clements e Felleisen mostram como esse problema pode ser solucionado usando uma técnica chamada "marcas de continuação" em seu artigo A Semântica Recursiva da Cauda para Inspeções de Pilha no ESOP 2003.
fonte