You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

The C++ Standard [ISO/IEC 14882-2003] Section 3.2 "One definition rule" says, in paragraph 3: "Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required." Although it is possible to check that the ODR is complied with (see [[Quinlan 06]]) compilers to not, at present, enforce the rule or even issue a diagnostic. As the paper by Quinlan, et al. shows, failing to enforce the ODR enables a virtual function pointer attack, known as the VPTR exploit.

Non-Compliant Code Example

This example is taken from the paper by Quinlan, et al. referenced above.

Base abstract class (Base.h)

class Base {
public:
    virtual ~Base () {}
    virtual void run () = 0;

Innocuous module (Module.cpp)

# include "Base.h"

class Derived: public Base {
public:
    Derived () {buf_[0] = 'a';}
    void run () {buf_[0] = 'z';}
    char buf_[1];
};

void runModule () {
    Derived a,b;
    Base *pa = &a, *pb = &b;
    pb->run ();  // Expect b.buf_[0] == 'z'
    pa->run ();  // Expect a.buf_[0] == 'z'
}

Malicious module (Attacker.cpp)

# include "Base.h"

class Attacker: public Base {
public: void run () {
        // vtable is overwritten
        // do malicious things here
        ...
    }
}

class Derived: public Base {  // Class violating ODR
public:
    void run () {
        buf_[0] = 'z';  // Looks normal, but ...
        Attacker x;  // Instantiate to get a vtable to inject
        *((unsigned *)(buf_ = 12)) = *((const unsigned *)(&x)):
    }
    char buf_[16];  // Buffer used to overwrite vtable
};

Derived d;  // Instantiate to get malicious Derived

Compliant Solution

The solution is to not allow more than one definition of a non-inline function or object to be admitted into a system.

Priority: P3 Level: L3

Failing to obey the ODR allows the VPTR exploit, which could lead to an attacker being able to execute arbitrary code.

Component

Value

Severity

3 (high)

Likelihood

1 (unlikely)

Remediation cost

1 (high)

References

  • Quinlan 06 Quinlan, Dan; et al. "Support for Whole-Program Analysis and the Verification of the One-Definition Rule in C++"
  • No labels