Si bien la mayoría de los procesadores tienen hardware diseñado para facilitar la implementación y el uso de una pila de estilo C típica, normalmente la pila se define con el compilador utilizando el código compilador incorporado.
Podría implementar su propio compilador que crea y utiliza un estilo de pila diferente. En su caso, estaría buscando implementar dos pilas separadas, una con variables de entrada, local y de retorno, y otra con ubicaciones de llamada / retorno. Puede implementar ambas pilas en una sección de la memoria que no se puede ejecutar, ni hacer referencia a los punteros en el resto del código, por lo que no puede modificarse, excepto por las llamadas a funciones definidas por el compilador y las devoluciones. Al ubicar las variables locales aparte de la pila de llamada / retorno, evitará algunos tipos de ataques de desbordamiento de búfer.
La Sección 10 de Conceptos básicos del diseño del compilador (Gratis, PDF, 1.6MB) explica las llamadas a funciones y la pila de llamadas. Si revisa esa sección, encontrará que el diseño de la pila que incluye tanto las llamadas como las variables locales es muy conveniente por varios motivos. Dividirlas podría aumentar la seguridad, pero estás desacelerando el procesador y el programa al tratar con dos pilas.
A excepción de los procesadores pequeños de propósito especial, como el microcontrolador PIC, no hay arquitecturas comunes que implementen el concepto que está preguntando. Sin embargo, hay un gran número de procesadores de investigación con varios métodos para prevenir ataques de desbordamiento de búfer , algunos de los cuales incluyen conceptos similares a los tuyos.
Sin embargo, incluso en esos procesadores, el trabajo del compilador es lidiar con la pila. La arquitectura del procesador simplemente proporciona herramientas adicionales para facilitar la protección del software contra ataques.
En su lugar, podría utilizar un lenguaje y un compilador diseñados de forma que no sean posibles los ataques de desbordamiento de búfer. Hoy en día, muchos lenguajes de alto nivel realizan la verificación de los límites de la matriz en cada acceso a la matriz, evitando ataques de desbordamiento de búfer. Esto es, en gran medida, un problema resuelto para muchos idiomas y sus compiladores.