1 // Compile with /home/llozano/local2/proj/vtable/gcc-root/usr/local/bin/g++ -m32 -fvtable-verify=std -fpic -rdynamic -Wl,-R,/home/llozano/local2/proj/vtable/gcc-root/usr/local/lib32:./lib32 -I/home/llozano/local2/proj/vtable/vt2/gcc-4_6-mobile-vtable-security//libstdc++-v3/libsupc++ temp_deriv.cc -O0 -ldl -lpthread -Wl,--whole-archive,-lvtv_init,--no-whole-archive,-z,relro -DTPID=0 -g
2 // Look at assembly with: objdump -drl a.out
3
4 #include <dlfcn.h>
5 #include <assert.h>
6
7 extern "C" int printf(const char *, ...);
8
9 static int counter = 0;
10
11 template <int i> struct base
12 {
incbase13 virtual void inc() { counter += i; }
14 };
15
16 template <int i> struct derived: base<i>
17 {
incderived18 virtual void inc() { counter += (10*i); }
19 };
20
21 // We don't use this class. It is just here so that the
22 // compiler does not devirtualize calls to derived::inc()
23 template <int i> struct derived2: derived<i>
24 {
incderived225 virtual void inc() { counter += (20*i); }
26 };
27
28 static base<TPID> * bp = new base<TPID>();
29 static derived<TPID> * dp = new derived<TPID>();
30 static base<TPID> * dbp = new derived<TPID>();
31
32 // Given 2 pointers to C++ objects (non PODs), exchange the pointers to vtable
exchange_vtptr(void * object1_ptr,void * object2_ptr)33 void exchange_vtptr(void * object1_ptr, void * object2_ptr)
34 {
35 void ** object1_vtptr_ptr = (void **)object1_ptr;
36 void ** object2_vtptr_ptr = (void **)object2_ptr;
37 void * object1_vtptr = *object1_vtptr_ptr;
38 void * object2_vtptr = *object2_vtptr_ptr;
39 *object1_vtptr_ptr = object2_vtptr;
40 *object2_vtptr_ptr = object1_vtptr;
41 }
42
main()43 main()
44 {
45 int prev_counter;
46
47 exchange_vtptr(bp, dp);
48 exchange_vtptr(bp, dp);
49 exchange_vtptr(bp, dbp);
50 exchange_vtptr(bp, dbp);
51
52 counter = 0;
53 bp->inc();
54 dp->inc();
55 dbp->inc();
56 assert(counter == (TPID + 10*TPID + 10*TPID));
57
58 prev_counter = counter;
59 exchange_vtptr(bp, dp);
60 bp->inc(); // This one should succeed but it is calling the wrong member
61 assert(counter == (prev_counter + 10*TPID));
62 printf("Pass first attack!\n");
63 dp->inc();
64 printf("TPDI=%d counter %d\n", TPID, counter);
65 printf("Pass second attack!\n");
66
67 }
68