2012-09-04 15 views
6

Es un patrón común para usar plantillas para forzar al compilador a inicializar valores de tipos primitivos/POD (https://stackoverflow.com/a/11493744/16673 o http://www.codeproject.com/Articles/825/Using-templates-for-initialization).Plantilla para realizar la sobrescritura automática de memoria en la destrucción

¿Existe un patrón similar que podría utilizarse para borrar el valor una vez que se sale del alcance por razones de seguridad, para asegurarse de que el valor no quede en la pila una vez que la variable se destruye? Me temo que una implementación análoga ingenua podría no funcionar, ya que el compilador puede ignorar cualquier asignación a un valor que está fuera del alcance, ya que se puede probar trivialmente que el valor ya no se usa. ¿Hay alguna solución consistente y razonablemente portátil, por ej. usando volátil?

Respuesta

3

Usted podría utilizar algunos C++ 11 características para hacer esto más portátil, pero esto puede ser suficiente como punto de partida:

Clase

template<typename T> 
class t_secure_destruct { 
    static const size_t Size = sizeof(T); 
    static const size_t Align = alignof(T); 
public: 
    t_secure_destruct() : d_memory() { 
    new(this->d_memory)T; 
    } 

    ~t_secure_destruct() { 
    reinterpret_cast<T*>(this->d_memory)->~T(); 
    this->scribble(); 
    } 

    // @todo implement or delete op-assign and remaining constructors 

public: 
    T& get() { 
    return *reinterpret_cast<T*>(this->d_memory); 
    } 

    const T& get() const { 
    return *reinterpret_cast<const T*>(this->d_memory); 
    } 

private: 
    void scribble() { 
    for (size_t idx(0); idx < Size; ++idx) { 
     this->d_memory[idx] = random(); 
    } 
    } 

private: 
    __attribute__((aligned(Align))) char d_memory[Size]; 
}; 

demostración

#include <iostream> 

class t_test { 
public: 
    t_test() : a(-1) { 
    std::cout << "construct\n"; 
    } 

    ~t_test() { 
    std::cout << "destruct\n"; 
    } 

public: 
    void print() const { 
    std::cout << "a = " << a << "\n"; 
    } 

public: 
    int a; 
}; 

int main(int argc, const char* argv[]) { 
    t_secure_destruct<t_test>test; 
    test.get().print(); 
    test.get().a = 100; 
    test.get().print(); 
    return 0; 
} 

Por supuesto, también puede respaldar esa asignación con una asignación de montón, si lo desea. Si necesita ser más astuto que un optimizador, es posible que tenga que dejar el escritor de calcomanías fuera de su alcance.

+0

Sonido razonable. Sin embargo, limpiar con randoms parece aportar pocos beneficios, la puesta a cero simple debería hacer el trabajo. La solución no intenta protegerse contra alguien que lee los chips de memoria o algo así, solo contra otro proceso de acceso a la memoria. ¿O hay alguna razón para usar datos aleatorios incluso en tal caso? – Suma

+0

La solución parece estar utilizando características (atributos) específicas de GCC. ¿Hay alguna razón para usar el char para el almacenamiento? ¿Por qué no usar el tipo original? – Suma

+0

@Suma depende completamente de lo que quiere lograr. los ceros también serían buenos, es solo una ilustración. – justin

4

Hay una función en la API de Windows llamada SecureZeroMemory. Podrías ver su implementación.

Sin embargo, en general, el compilador se ve obligado a respetar las escrituras volátiles. Si hizo que la variable fuese volátil, no debería poder eliminar escrituras.

+0

Lo que escriba sobre volátiles probablemente sea una pista de cómo sería la respuesta a esta pregunta (la plantilla probablemente debería usar volátil en el destructor), pero me parece que realmente responde la pregunta (la variable segura no está marcada como volátil) , y no esperaba que se marque como tal, esto debe ser manejado por una plantilla si es necesario). – Suma

+1

@Suma: no importa que la variable en sí no sea volátil. Es suficiente que la escritura sea a través de una expresión volátil, como '* const_cast (this)'. Hacer que la variable sea volátil garantiza que 'this' en sí mismo sea' Foo volátil * 'en todas partes sin moldes, pero solo necesita una expresión volátil en el dtor. – MSalters

Cuestiones relacionadas