1 /* Copyright (C) 2012-2021 Free Software Foundation, Inc.
2 
3  This file is part of GCC.
4 
5  GCC is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 3, or (at your option)
8  any later version.
9 
10  GCC is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14 
15  Under Section 7 of GPL version 3, you are granted additional
16  permissions described in the GCC Runtime Library Exception, version
17  3.1, as published by the Free Software Foundation.
18 
19  You should have received a copy of the GNU General Public License and
20  a copy of the GCC Runtime Library Exception along with this program;
21  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22  <http://www.gnu.org/licenses/>.  */
23 
24 /* This file is part of the vtable security feature implementation.
25    The vtable security feature is designed to detect when a virtual
26    call is about to be made through an invalid vtable pointer
27    (possibly due to data corruption or malicious attacks). The
28    compiler finds every virtual call, and inserts a verification call
29    before the virtual call.  The verification call takes the actual
30    vtable pointer value in the object through which the virtual call
31    is being made, and compares the vtable pointer against a set of all
32    valid vtable pointers that the object could contain (this set is
33    based on the declared type of the object).  If the pointer is in
34    the valid set, execution is allowed to continue; otherwise the
35    program is halted.
36 
37   There are several pieces needed in order to make this work: 1. For
38   every virtual class in the program (i.e. a class that contains
39   virtual methods), we need to build the set of all possible valid
40   vtables that an object of that class could point to.  This includes
41   vtables for any class(es) that inherit from the class under
42   consideration.  2. For every such data set we build up, we need a
43   way to find and reference the data set.  This is complicated by the
44   fact that the real vtable addresses are not known until runtime,
45   when the program is loaded into memory, but we need to reference the
46   sets at compile time when we are inserting verification calls into
47   the program.  3.  We need to find every virtual call in the program,
48   and insert the verification call (with the appropriate arguments)
49   before the virtual call.  4. We need some runtime library pieces:
50   the code to build up the data sets at runtime; the code to actually
51   perform the verification using the data sets; and some code to set
52   protections on the data sets, so they themselves do not become
53   hacker targets.
54 
55   To find and reference the set of valid vtable pointers for any given
56   virtual class, we create a special global varible for each virtual
57   class.  We refer to this as the "vtable map variable" for that
58   class.  The vtable map variable has the type "void *", and is
59   initialized by the compiler to NULL.  At runtime when the set of
60   valid vtable pointers for a virtual class, e.g. class Foo, is built,
61   the vtable map variable for class Foo is made to point to the set.
62   During compile time, when the compiler is inserting verification
63   calls into the program, it passes the vtable map variable for the
64   appropriate class to the verification call, so that at runtime the
65   verification call can find the appropriate data set.
66 
67   The actual set of valid vtable pointers for a polymorphic class,
68   e.g. class Foo, cannot be built until runtime, when the vtables get
69   loaded into memory and their addresses are known.  But the knowledge
70   about which vtables belong in which class' hierarchy is only known
71   at compile time.  Therefore at compile time we collect class
72   hierarchy and vtable information about every virtual class, and we
73   generate calls to build up the data sets at runtime.  To build the
74   data sets, we call one of the functions we add to the runtime
75   library, __VLTRegisterPair.  __VLTRegisterPair takes two arguments,
76   a vtable map variable and the address of a vtable.  If the vtable
77   map variable is currently NULL, it creates a new data set (hash
78   table), makes the vtable map variable point to the new data set, and
79   inserts the vtable address into the data set.  If the vtable map
80   variable is not NULL, it just inserts the vtable address into the
81   data set.  In order to make sure that our data sets are built before
82   any verification calls happen, we create a special constructor
83   initialization function for each compilation unit, give it a very
84   high initialization priority, and insert all of our calls to
85   __VLTRegisterPair into our special constructor initialization
86   function.  */
87 
88 /* This file contains the main externally visible runtime library
89    functions for vtable verification: __VLTChangePermission,
90    __VLTRegisterPair, and __VLTVerifyVtablePointer.  It also contains
91    debug versions __VLTRegisterPairDebug and
92    __VLTVerifyVtablePointerDebug, which have extra parameters in order
93    to make it easier to debug verification failures.
94 
95    The final piece of functionality implemented in this file is symbol
96    resolution for multiple instances of the same vtable map variable.
97    If the same virtual class is used in two different compilation
98    units, then each compilation unit will create a vtable map variable
99    for the class.  We need all instances of the same vtable map
100    variable to point to the same (single) set of valid vtable
101    pointers for the class, so we wrote our own hashtable-based symbol
102    resolution for vtable map variables (with a tiny optimization in
103    the case where there is only one instance of the variable).
104 
105    There are two other important pieces to the runtime for vtable
106    verification besides the main pieces that go into libstdc++.so: two
107    special tiny shared libraries, libvtv_init.so and libvtv_stubs.so.
108    libvtv_init.so is built from vtv_init.cc.  It is designed to help
109    minimize the calls made to mprotect (see the comments in
110    vtv_init.cc for more details).  Anything compiled with
111    "-fvtable-verify=std" must be linked with libvtv_init.so (the gcc
112    driver has been modified to do this).  vtv_stubs.so is built from
113    vtv_stubs.cc.  It replaces the main runtime functions
114    (__VLTChangePermissino, __VLTRegisterPair and
115    __VLTVerifyVtablePointer) with stub functions that do nothing.  If
116    a programmer has a library that was built with verification, but
117    wishes to not have verification turned on, the programmer can link
118    in the vtv_stubs.so library.  */
119 
120 #include <stdlib.h>
121 #include <stdio.h>
122 #include <string.h>
123 #if defined (__CYGWIN__) || defined (__MINGW32__)
124 #include <windows.h>
125 #include <winternl.h>
126 #include <psapi.h>
127 #else
128 #include <execinfo.h>
129 #endif
130 
131 #include <unistd.h>
132 #if !defined (__CYGWIN__) && !defined (__MINGW32__)
133 #include <sys/mman.h>
134 #include <link.h>
135 #endif
136 #include <errno.h>
137 #include <fcntl.h>
138 #include <limits.h>
139 
140 /* For gthreads suppport */
141 #include <bits/c++config.h>
142 #include <ext/concurrence.h>
143 
144 #include "vtv_utils.h"
145 #include "vtv_malloc.h"
146 #include "vtv_set.h"
147 #include "vtv_map.h"
148 #include "vtv_rts.h"
149 #include "vtv_fail.h"
150 
151 #include "vtv-change-permission.h"
152 
153 #ifdef HAVE_GETEXECNAME
154 const char *program_invocation_name;
155 #endif
156 
157 #ifdef HAVE___FORTIFY_FAIL
158 extern "C" {
159 
160   /* __fortify_fail is a function in glibc that calls __libc_message,
161      causing it to print out a program termination error message
162      (including the name of the binary being terminated), a stack
163      trace where the error occurred, and a memory map dump.  Ideally
164      we would have called __libc_message directly, but that function
165      does not appear to be accessible to functions outside glibc,
166      whereas __fortify_fail is.  We call __fortify_fail from
167      __vtv_really_fail.  We looked at calling __libc_fatal, which is
168      externally accessible, but it does not do the back trace and
169      memory dump.  */
170 
171   extern void __fortify_fail (const char *) __attribute__((noreturn));
172 
173 } /* extern "C" */
174 #else
175 #if defined (__CYGWIN__) || defined (__MINGW32__)
176 // porting: fix link error to libc
__fortify_fail(const char * msg)177 void __fortify_fail (const char * msg){
178     OutputDebugString(msg);
179     abort();
180 }
181 #else
182 // FIXME: Provide backtrace via libbacktrace?
__fortify_fail(const char * msg)183 void __fortify_fail (const char *msg) {
184     write (2, msg, strlen (msg));
185     abort ();
186 }
187 #endif
188 #endif
189 
190 /* The following variables are used only for debugging and performance
191    tuning purposes. Therefore they do not need to be "protected".
192    They cannot be used to attack the vtable verification system and if
193    they become corrupted it will not affect the correctness or
194    security of any of the rest of the vtable verification feature.  */
195 
196 unsigned int num_calls_to_regset = 0;
197 unsigned int num_calls_to_regpair = 0;
198 unsigned int num_calls_to_verify_vtable = 0;
199 unsigned long long regset_cycles = 0;
200 unsigned long long regpair_cycles = 0;
201 unsigned long long verify_vtable_cycles = 0;
202 
203 /* Be careful about initialization of statics in this file.  Some of
204    the routines below are called before any runtime initialization for
205    statics in this file will be done. For example, dont try to
206    initialize any of these statics with a runtime call (for ex:
207    sysconf). The initialization will happen after calls to the routines
208    to protect/unprotec the vtabla_map variables */
209 
210 /* No need to mark the following variables with VTV_PROTECTED_VAR.
211    These are either const or are only used for debugging/tracing.
212    debugging/tracing will not be ON on production environments */
213 
214 static const bool debug_hash = HASHTABLE_STATS;
215 
216 #ifdef VTV_DEBUG
217 static const int debug_functions = 1;
218 static const int debug_init = 1;
219 static const int debug_verify_vtable = 1;
220 #else
221 static const int debug_functions = 0;
222 static const int debug_init = 0;
223 static const int debug_verify_vtable = 0;
224 #endif
225 
226 /* Global file descriptor variables for logging, tracing and debugging.  */
227 
228 static int init_log_fd = -1;
229 static int verify_vtable_log_fd = -1;
230 
231 /* This holds a formatted error logging message, to be written to the
232    vtable verify failures log.  */
233 static char debug_log_message[1024];
234 
235 
236 #ifdef __GTHREAD_MUTEX_INIT
237 static __gthread_mutex_t change_permissions_lock = __GTHREAD_MUTEX_INIT;
238 #else
239 static __gthread_mutex_t change_permissions_lock;
240 #endif
241 
242 
243 #ifndef VTV_STATS
244 #define VTV_STATS 0
245 #endif
246 
247 #if VTV_STATS
248 
249 static inline unsigned long long
get_cycle_count(void)250 get_cycle_count (void)
251 {
252   return rdtsc();
253 }
254 
255 static inline void
accumulate_cycle_count(unsigned long long * sum,unsigned long long start)256 accumulate_cycle_count (unsigned long long *sum, unsigned long long start)
257 {
258   unsigned long long end = rdtsc();
259   *sum = *sum + (end - start);
260 }
261 
262 static inline void
increment_num_calls(unsigned int * num_calls)263 increment_num_calls (unsigned int *num_calls)
264 {
265   *num_calls = *num_calls + 1;
266 }
267 
268 #else
269 
270 static inline unsigned long long
get_cycle_count(void)271 get_cycle_count (void)
272 {
273   return (unsigned long long) 0;
274 }
275 
276 static inline void
accumulate_cycle_count(unsigned long long * sum,unsigned long long start)277 accumulate_cycle_count (unsigned long long *sum __attribute__((__unused__)),
278                         unsigned long long start __attribute__((__unused__)))
279 {
280   /* Do nothing.  */
281 }
282 
283 static inline void
increment_num_calls(unsigned int * num_calls)284 increment_num_calls (unsigned int *num_calls __attribute__((__unused__)))
285 {
286   /* Do nothing.  */
287 }
288 
289 #endif
290 
291 /* Types needed by insert_only_hash_sets.  */
292 typedef uintptr_t int_vptr;
293 
294 /* The set of valid vtable pointers for each virtual class is stored
295    in a hash table.  This is the hashing function used for the hash
296    table.  For more information on the implementation of the hash
297    table, see the class insert_only_hash_sets in vtv_set.h.  */
298 
299 struct vptr_hash
300   {
301     /* Hash function, used to convert vtable pointer, V, (a memory
302        address) into an index into the hash table.  */
303     size_t
operator ()vptr_hash304     operator() (int_vptr v) const
305       {
306 	const uint32_t x = 0x7a35e4d9;
307 	const int shift = (sizeof (v) == 8) ? 23 : 21;
308 	v = x * v;
309 	return v ^ (v >> shift);
310       }
311   };
312 
313 /* This is the memory allocator used to create the hash table data
314    sets of valid vtable pointers.  We use VTV_malloc in order to keep
315    track of which pages have been allocated, so we can update the
316    protections on those pages appropriately.  See the class
317    insert_only_hash_sets in vtv_set.h for more information.  */
318 
319 struct vptr_set_alloc
320   {
321     /* Memory allocator operator.  N is the number of bytes to be
322        allocated.  */
323     void *
operator ()vptr_set_alloc324     operator() (size_t n) const
325       {
326 	return __vtv_malloc (n);
327       }
328   };
329 
330 /* Instantiate the template classes (in vtv_set.h) for our particular
331    hash table needs.  */
332 typedef insert_only_hash_sets<int_vptr, vptr_hash, vptr_set_alloc> vtv_sets;
333 typedef vtv_sets::insert_only_hash_set vtv_set;
334 typedef vtv_set * vtv_set_handle;
335 typedef vtv_set_handle * vtv_set_handle_handle;
336 
337 /* Records for caching the section header information that we have
338    read out of the file(s) on disk (in dl_iterate_phdr_callback), to
339    avoid having to re-open and re-read the same file multiple
340    times.  */
341 
342 struct sect_hdr_data
343 {
344 #if defined (__CYGWIN__) || defined (__MINGW32__)
345   uintptr_t dlpi_addr;    /* The header address in the INFO record,
346                             passed in from dl_iterate_phdr.  */
347   uintptr_t mp_low;       /* Start address of the .vtable_map_vars
348                             section in memory.  */
349 #else
350   ElfW (Addr) dlpi_addr; /* The header address in the INFO record,
351                             passed in from dl_iterate_phdr.  */
352   ElfW (Addr) mp_low;    /* Start address of the .vtable_map_vars
353                             section in memory.  */
354 #endif
355   size_t mp_size;        /* Size of the .vtable_map_vars section in
356                             memory.  */
357 };
358 
359 /* Array for caching the section header information, read from file,
360    to avoid re-opening and re-reading the same file over-and-over
361    again.  */
362 
363 #define MAX_ENTRIES 250
364 static struct sect_hdr_data vtv_sect_info_cache[MAX_ENTRIES] VTV_PROTECTED_VAR;
365 
366 unsigned int num_cache_entries VTV_PROTECTED_VAR = 0;
367 
368 /* This function takes the LOAD_ADDR for an object opened by the
369    dynamic loader, and checks the array of cached file data to see if
370    there is an entry with the same addres.  If it finds such an entry,
371    it returns the record for that entry; otherwise it returns
372    NULL.  */
373 
374 #if defined (__CYGWIN__) || defined (__MINGW32__)
375 struct sect_hdr_data *
search_cached_file_data(uintptr_t load_addr)376 search_cached_file_data (uintptr_t load_addr)
377 #else
378 struct sect_hdr_data *
379 search_cached_file_data (ElfW (Addr) load_addr)
380 #endif
381 {
382   unsigned int i;
383   for (i = 0; i < num_cache_entries; ++i)
384     {
385       if (vtv_sect_info_cache[i].dlpi_addr == load_addr)
386         return &(vtv_sect_info_cache[i]);
387     }
388 
389   return NULL;
390 }
391 
392 /* This function tries to read COUNT bytes out of the file referred to
393    by FD into the buffer BUF.  It returns the actual number of bytes
394    it succeeded in reading.  */
395 
396 static size_t
ReadPersistent(int fd,void * buf,size_t count)397 ReadPersistent (int fd, void *buf, size_t count)
398 {
399   char *buf0 = (char *) buf;
400   size_t num_bytes = 0;
401   while (num_bytes < count)
402     {
403       int len;
404       len = read (fd, buf0 + num_bytes, count - num_bytes);
405       if (len < 0)
406 	return -1;
407       if (len == 0)
408 	break;
409       num_bytes += len;
410     }
411 
412   return num_bytes;
413 }
414 
415 /* This function tries to read COUNT bytes, starting at OFFSET from
416    the file referred to by FD, and put them into BUF.  It calls
417    ReadPersistent to help it do so.  It returns the actual number of
418    bytes read, or -1 if it fails altogether.  */
419 
420 static size_t
ReadFromOffset(int fd,void * buf,const size_t count,const off_t offset)421 ReadFromOffset (int fd, void *buf, const size_t count, const off_t offset)
422 {
423   off_t off = lseek (fd, offset, SEEK_SET);
424   if (off != (off_t) -1)
425     return ReadPersistent (fd, buf, count);
426   return -1;
427 }
428 
429 /* The function takes a MESSAGE and attempts to write it to the vtable
430    memory protection log (for debugging purposes).  If the file is not
431    open, it attempts to open the file first.  */
432 
433 static void
log_memory_protection_data(char * message)434 log_memory_protection_data (char *message)
435 {
436   static int log_fd = -1;
437 
438   if (log_fd == -1)
439     log_fd = __vtv_open_log ("vtv_memory_protection_data.log");
440 
441   __vtv_add_to_log (log_fd, "%s", message);
442 }
443 
444 #if defined (__CYGWIN__) || defined (__MINGW32__)
445 static void
read_section_offset_and_length(char * name,uintptr_t addr,const char * sect_name,int mprotect_flags,off_t * sect_offset,WORD * sect_len)446 read_section_offset_and_length (char *name,
447                                 uintptr_t addr,
448                                 const char *sect_name,
449                                 int mprotect_flags,
450                                 off_t *sect_offset,
451                                 WORD *sect_len)
452 {
453   bool found = false;
454   struct sect_hdr_data *cached_data = NULL;
455 
456   /* Check to see if we already have the data for this file.  */
457   cached_data = search_cached_file_data (addr);
458 
459   if (cached_data)
460     {
461       *sect_offset = cached_data->mp_low;
462       *sect_len = cached_data->mp_size;
463       return;
464     }
465 
466   // check for DOS Header magic bytes
467   if (*(WORD *)addr == 0x5A4D)
468     {
469       int name_len = strlen (sect_name);
470       int fd = -1;
471 
472       /* Attempt to open the binary file on disk.  */
473       if (strlen (name) == 0)
474         {
475           return;
476         }
477       else
478         fd = open (name, O_RDONLY | O_BINARY);
479 
480       if (fd != -1)
481         {
482           /* Find the section header information in memory.  */
483           PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)addr;
484           PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((char *)addr
485                                           + pDosHeader->e_lfanew);
486           PIMAGE_FILE_HEADER pFileHeader = &pNtHeaders->FileHeader;
487 
488           DWORD PointerToStringTable = pFileHeader->PointerToSymbolTable
489                                         + (pFileHeader->NumberOfSymbols*0x12);
490 
491           PIMAGE_SECTION_HEADER sect_hdr =
492             (PIMAGE_SECTION_HEADER)((char *)&pNtHeaders->OptionalHeader
493                                        + pFileHeader->SizeOfOptionalHeader);
494 
495           /* Loop through all the section headers, looking for one whose
496              name is ".vtable_map_vars".  */
497 
498           for (int i = 0; i < pFileHeader->NumberOfSections && !found; ++i)
499             {
500               char header_name[64];
501 
502               /* Check if we have to get the section name from the COFF string
503                  table. */
504               if (sect_hdr[i].Name[0] == '/')
505                 {
506                   if (atoi((const char*)sect_hdr[i].Name+1) == 0)
507                     {
508                       continue;
509                     }
510 
511                   off_t name_offset = PointerToStringTable
512                                        + atoi((const char*)sect_hdr[i].Name+1);
513 
514                   size_t bytes_read = ReadFromOffset (fd, &header_name, 64,
515                                                       name_offset);
516 
517                   VTV_ASSERT (bytes_read > 0);
518                 }
519               else
520                 {
521                   memcpy (&header_name, sect_hdr[i].Name,
522                           sizeof (sect_hdr[i].Name));
523                 }
524 
525               if (memcmp (header_name, sect_name, name_len) == 0)
526                 {
527                   /* We found the section; get its load offset and
528                      size.  */
529                   *sect_offset = sect_hdr[i].VirtualAddress;
530       if (sect_hdr[i].Misc.VirtualSize % VTV_PAGE_SIZE != 0)
531         *sect_len = sect_hdr[i].Misc.VirtualSize + VTV_PAGE_SIZE
532                      - (sect_hdr[i].Misc.VirtualSize % VTV_PAGE_SIZE);
533       else
534         *sect_len = sect_hdr[i].Misc.VirtualSize;
535                   found = true;
536                 }
537             }
538           close (fd);
539         }
540     }
541 
542   if (*sect_offset != 0 && *sect_len != 0)
543     {
544       /* Calculate the page location in memory, making sure the
545          address is page-aligned.  */
546       uintptr_t start_addr = addr + *sect_offset;
547       *sect_offset = start_addr & ~(VTV_PAGE_SIZE - 1);
548       *sect_len = *sect_len - 1;
549 
550       /* Since we got this far, we must not have found these pages in
551          the cache, so add them to it.  NOTE: We could get here either
552          while making everything read-only or while making everything
553          read-write.  We will only update the cache if we get here on
554          a read-write (to make absolutely sure the cache is writable
555          -- also the read-write pass should come before the read-only
556          pass).  */
557       if ((mprotect_flags & PROT_WRITE)
558           && num_cache_entries < MAX_ENTRIES)
559         {
560           vtv_sect_info_cache[num_cache_entries].dlpi_addr = addr;
561           vtv_sect_info_cache[num_cache_entries].mp_low = *sect_offset;
562           vtv_sect_info_cache[num_cache_entries].mp_size = *sect_len;
563           num_cache_entries++;
564         }
565     }
566 }
567 #else
568 static void
read_section_offset_and_length(struct dl_phdr_info * info,const char * sect_name,int mprotect_flags,off_t * sect_offset,ElfW (Word)* sect_len)569 read_section_offset_and_length (struct dl_phdr_info *info,
570                                 const char *sect_name,
571                                 int mprotect_flags,
572                                 off_t *sect_offset,
573                                 ElfW (Word) *sect_len)
574 {
575   char program_name[PATH_MAX];
576   char *cptr;
577   bool found = false;
578   struct sect_hdr_data *cached_data = NULL;
579   const ElfW (Phdr) *phdr_info = info->dlpi_phdr;
580   const ElfW (Ehdr) *ehdr_info =
581     (const ElfW (Ehdr) *) (info->dlpi_addr + info->dlpi_phdr[0].p_vaddr
582                            - info->dlpi_phdr[0].p_offset);
583 
584 
585   /* Get the name of the main executable.  This may or may not include
586      arguments passed to the program.  Find the first space, assume it
587      is the start of the argument list, and change it to a '\0'. */
588 #ifdef HAVE_GETEXECNAME
589   program_invocation_name = getexecname ();
590 #endif
591   snprintf (program_name, sizeof (program_name), program_invocation_name);
592 
593   /* Check to see if we already have the data for this file.  */
594   cached_data = search_cached_file_data (info->dlpi_addr);
595 
596   if (cached_data)
597     {
598       *sect_offset = cached_data->mp_low;
599       *sect_len = cached_data->mp_size;
600       return;
601     }
602 
603   /* Find the first non-escaped space in the program name and make it
604      the end of the string.  */
605   cptr = strchr (program_name, ' ');
606   if (cptr != NULL && cptr[-1] != '\\')
607     cptr[0] = '\0';
608 
609   if ((phdr_info->p_type == PT_PHDR || phdr_info->p_type == PT_LOAD)
610       && (ehdr_info->e_shoff && ehdr_info->e_shnum))
611     {
612       int name_len = strlen (sect_name);
613       int fd = -1;
614 
615       /* Attempt to open the binary file on disk.  */
616       if (strlen (info->dlpi_name) == 0)
617         {
618           /* If the constructor initialization function was put into
619              the preinit array, then this function will get called
620              while handling preinit array stuff, in which case
621              program_invocation_name has not been initialized.  In
622              that case we can get the filename of the executable from
623              "/proc/self/exe".  */
624           if (strlen (program_name) > 0)
625             {
626               if (phdr_info->p_type == PT_PHDR)
627                 fd = open (program_name, O_RDONLY);
628             }
629           else
630             fd = open ("/proc/self/exe", O_RDONLY);
631         }
632       else
633         fd = open (info->dlpi_name, O_RDONLY);
634 
635       if (fd != -1)
636         {
637           /* Find the section header information in the file.  */
638           ElfW (Half) strtab_idx = ehdr_info->e_shstrndx;
639           ElfW (Shdr) shstrtab;
640           off_t shstrtab_offset = ehdr_info->e_shoff +
641                                          (ehdr_info->e_shentsize * strtab_idx);
642           size_t bytes_read = ReadFromOffset (fd, &shstrtab, sizeof (shstrtab),
643                                               shstrtab_offset);
644           VTV_ASSERT (bytes_read == sizeof (shstrtab));
645 
646           ElfW (Shdr) sect_hdr;
647 
648 	  /* This code will be needed once we have crated libvtv.so. */
649 	  bool is_libvtv = false;
650 
651 	  /*
652 	  if (strstr (info->dlpi_name, "libvtv.so"))
653 	    is_libvtv = true;
654 	  */
655 
656           /* Loop through all the section headers, looking for one whose
657              name is ".vtable_map_vars".  */
658 
659           for (int i = 0; i < ehdr_info->e_shnum && !found; ++i)
660             {
661               off_t offset = ehdr_info->e_shoff + (ehdr_info->e_shentsize * i);
662 
663               bytes_read = ReadFromOffset (fd, &sect_hdr, sizeof (sect_hdr),
664                                            offset);
665 
666               VTV_ASSERT (bytes_read == sizeof (sect_hdr));
667 
668               char header_name[64];
669               off_t name_offset = shstrtab.sh_offset +  sect_hdr.sh_name;
670 
671               bytes_read = ReadFromOffset (fd, &header_name, 64, name_offset);
672 
673               VTV_ASSERT (bytes_read > 0);
674 
675               if (memcmp (header_name, sect_name, name_len) == 0)
676                 {
677                   /* We found the section; get its load offset and
678                      size.  */
679                   *sect_offset = sect_hdr.sh_addr;
680 		  if (!is_libvtv)
681 		    {
682 		      VTV_ASSERT (sect_hdr.sh_size - VTV_PAGE_SIZE >= 0);
683 		      *sect_len = sect_hdr.sh_size - VTV_PAGE_SIZE;
684 		    }
685 		  else
686 		    *sect_len = sect_hdr.sh_size;
687                   found = true;
688                 }
689             }
690           close (fd);
691         }
692     }
693 
694   if (*sect_offset != 0 && *sect_len != 0)
695     {
696       /* Calculate the page location in memory, making sure the
697          address is page-aligned.  */
698       ElfW (Addr) start_addr = (const ElfW (Addr)) info->dlpi_addr
699                                                                  + *sect_offset;
700       *sect_offset = start_addr & ~(VTV_PAGE_SIZE - 1);
701       *sect_len = *sect_len - 1;
702 
703       /* Since we got this far, we must not have found these pages in
704          the cache, so add them to it.  NOTE: We could get here either
705          while making everything read-only or while making everything
706          read-write.  We will only update the cache if we get here on
707          a read-write (to make absolutely sure the cache is writable
708          -- also the read-write pass should come before the read-only
709          pass).  */
710       if ((mprotect_flags & PROT_WRITE)
711           && num_cache_entries < MAX_ENTRIES)
712         {
713           vtv_sect_info_cache[num_cache_entries].dlpi_addr = info->dlpi_addr;
714           vtv_sect_info_cache[num_cache_entries].mp_low = *sect_offset;
715           vtv_sect_info_cache[num_cache_entries].mp_size = *sect_len;
716           num_cache_entries++;
717         }
718     }
719 }
720 #endif
721 
722 #if defined (__CYGWIN__) || defined (__MINGW32__)
723 /* This function is used to iterate over all loaded modules and searches
724    for a section called ".vtable_map_vars". The only interaction with
725    the binary file on disk of the module is to read section names in the
726    COFF string table. If the module contains a ".vtable_map_vars" section,
727    read section offset and size from the section header of the loaded module.
728    Call 'mprotect' on those pages, setting the protection either to
729    read-only or read-write, depending on what's in data.
730    The calls to change the protection occur in vtv_unprotect_vtable_vars
731    and vtv_protect_vtable_vars.  */
732 
733 static int
iterate_modules(void * data)734 iterate_modules (void *data)
735 {
736   int * mprotect_flags = (int *) data;
737   off_t map_sect_offset = 0;
738   WORD map_sect_len = 0;
739   char buffer[1024];
740   const char *map_sect_name = VTV_PROTECTED_VARS_SECTION;
741   HMODULE hMods[1024];
742   HANDLE hProcess;
743   DWORD cbNeeded;
744 
745   hProcess = GetCurrentProcess ();
746 
747   if (NULL == hProcess)
748     return 0;
749 
750   if (EnumProcessModules (hProcess, hMods, sizeof (hMods), &cbNeeded))
751     {
752       /* Iterate over all loaded modules. */
753       for (unsigned int i = 0; i < (cbNeeded / sizeof (HMODULE)); i++)
754         {
755           char szModName[MAX_PATH];
756 
757           if (GetModuleFileNameExA (hProcess, hMods[i], szModName,
758                         sizeof (szModName)))
759             {
760               map_sect_offset = 0;
761               map_sect_len = 0;
762               read_section_offset_and_length (szModName,
763                                               (uintptr_t) hMods[i],
764                                               map_sect_name,
765                                               *mprotect_flags,
766                                               &map_sect_offset,
767                                               &map_sect_len);
768 
769               if (debug_functions)
770                 {
771                   snprintf (buffer, sizeof(buffer),
772                 "  Looking at load module %s to change permissions to %s\n",
773                 szModName,
774                 (*mprotect_flags & PROT_WRITE) ? "READ/WRITE" : "READ-ONLY");
775                   log_memory_protection_data (buffer);
776                 }
777 
778               /* See if we actually found the section.  */
779               if (map_sect_offset && map_sect_len)
780                 {
781                   unsigned long long start;
782                   int result;
783 
784                   if (debug_functions)
785                     {
786                       snprintf (buffer, sizeof (buffer),
787                                 "  (%s): Protecting %p to %p\n",
788                                 szModName,
789                                 (void *) map_sect_offset,
790                                 (void *) (map_sect_offset + map_sect_len));
791                       log_memory_protection_data (buffer);
792                     }
793 
794                   /* Change the protections on the pages for the section.  */
795 
796                   start = get_cycle_count ();
797                   result = mprotect ((void *) map_sect_offset, map_sect_len,
798                                      *mprotect_flags);
799                   accumulate_cycle_count (&mprotect_cycles, start);
800                   if (result == -1)
801                     {
802                       if (debug_functions)
803                         {
804                           snprintf (buffer, sizeof (buffer),
805                                     "Failed call to mprotect for %s error: ",
806                                     (*mprotect_flags & PROT_WRITE) ?
807                                     "READ/WRITE" : "READ-ONLY");
808                           log_memory_protection_data (buffer);
809                           perror(NULL);
810                         }
811                       VTV_error();
812                     }
813                   else
814                     {
815                       if (debug_functions)
816                        {
817                           snprintf (buffer, sizeof (buffer),
818                                     "mprotect'ed range [%p, %p]\n",
819                                     (void *) map_sect_offset,
820                                     (char *) map_sect_offset + map_sect_len);
821                           log_memory_protection_data (buffer);
822                         }
823                     }
824                   increment_num_calls (&num_calls_to_mprotect);
825                   num_pages_protected += (map_sect_len + VTV_PAGE_SIZE - 1)
826 		    / VTV_PAGE_SIZE;
827                   continue;
828                 }
829             }
830         }
831     }
832 
833     CloseHandle(hProcess);
834 
835   return 0;
836 }
837 #else
838 /* This is the callback function used by dl_iterate_phdr (which is
839    called from vtv_unprotect_vtable_vars and vtv_protect_vtable_vars).
840    It attempts to find the binary file on disk for the INFO record
841    that dl_iterate_phdr passes in; open the binary file, and read its
842    section header information.  If the file contains a
843    ".vtable_map_vars" section, read the section offset and size.  Use
844    the section offset and size, in conjunction with the data in INFO
845    to locate the pages in memory where the section is.  Call
846    'mprotect' on those pages, setting the protection either to
847    read-only or read-write, depending on what's in DATA.  */
848 
849 static int
dl_iterate_phdr_callback(struct dl_phdr_info * info,size_t,void * data)850 dl_iterate_phdr_callback (struct dl_phdr_info *info, size_t, void *data)
851 {
852   int * mprotect_flags = (int *) data;
853   off_t map_sect_offset = 0;
854   ElfW (Word) map_sect_len = 0;
855   char buffer[1024];
856   char program_name[1024];
857   const char *map_sect_name = VTV_PROTECTED_VARS_SECTION;
858 
859   /* Check to see if this is the record for the Linux Virtual Dynamic
860      Shared Object (linux-vdso.so.1), which exists only in memory (and
861      therefore cannot be read from disk).  */
862 
863   if (strcmp (info->dlpi_name, "linux-vdso.so.1") == 0)
864     return 0;
865 
866   if (strlen (info->dlpi_name) == 0
867       && info->dlpi_addr != 0)
868     return 0;
869 
870   /* Get the name of the main executable.  This may or may not include
871      arguments passed to the program.  Find the first space, assume it
872      is the start of the argument list, and change it to a '\0'. */
873 #ifdef HAVE_GETEXECNAME
874   program_invocation_name = getexecname ();
875 #endif
876   snprintf (program_name, sizeof (program_name), program_invocation_name);
877 
878   read_section_offset_and_length (info, map_sect_name, *mprotect_flags,
879 				  &map_sect_offset, &map_sect_len);
880 
881   if (debug_functions)
882     {
883       snprintf (buffer, sizeof(buffer),
884 		"  Looking at load module %s to change permissions to %s\n",
885 		((strlen (info->dlpi_name) == 0) ? program_name
886                                                  : info->dlpi_name),
887 		(*mprotect_flags & PROT_WRITE) ? "READ/WRITE" : "READ-ONLY");
888       log_memory_protection_data (buffer);
889     }
890 
891   /* See if we actually found the section.  */
892   if (map_sect_offset && map_sect_len)
893     {
894       unsigned long long start;
895       int result;
896 
897       if (debug_functions)
898         {
899           snprintf (buffer, sizeof (buffer),
900                     "  (%s): Protecting %p to %p\n",
901                     ((strlen (info->dlpi_name) == 0) ? program_name
902                      : info->dlpi_name),
903                     (void *) map_sect_offset,
904                     (void *) (map_sect_offset + map_sect_len));
905           log_memory_protection_data (buffer);
906         }
907 
908       /* Change the protections on the pages for the section.  */
909 
910       start = get_cycle_count ();
911       result = mprotect ((void *) map_sect_offset, map_sect_len,
912                          *mprotect_flags);
913       accumulate_cycle_count (&mprotect_cycles, start);
914       if (result == -1)
915         {
916           if (debug_functions)
917             {
918               snprintf (buffer, sizeof (buffer),
919                         "Failed call to mprotect for %s error: ",
920                         (*mprotect_flags & PROT_WRITE) ?
921                         "READ/WRITE" : "READ-ONLY");
922               log_memory_protection_data (buffer);
923               perror(NULL);
924             }
925           VTV_error();
926         }
927       else
928         {
929           if (debug_functions)
930            {
931               snprintf (buffer, sizeof (buffer),
932                         "mprotect'ed range [%p, %p]\n",
933                         (void *) map_sect_offset,
934                         (char *) map_sect_offset + map_sect_len);
935               log_memory_protection_data (buffer);
936             }
937         }
938       increment_num_calls (&num_calls_to_mprotect);
939       num_pages_protected += (map_sect_len + VTV_PAGE_SIZE - 1) / VTV_PAGE_SIZE;
940     }
941 
942   return 0;
943 }
944 #endif
945 
946 /* This function explicitly changes the protection (read-only or read-write)
947    on the vtv_sect_info_cache, which is used for speeding up look ups in the
948    function dl_iterate_phdr_callback.  This data structure needs to be
949    explicitly made read-write before any calls  to dl_iterate_phdr_callback,
950    because otherwise it may still be read-only when dl_iterate_phdr_callback
951    attempts to write to it.
952 
953    More detailed explanation:  dl_iterate_phdr_callback finds all the
954    .vtable_map_vars sections in all loaded objects (including the main program)
955    and (depending on where it was called from) either makes all the pages in the
956    sections read-write or read-only.  The vtv_sect_info_cache should be in the
957    .vtable_map_vars section for libstdc++.so, which means that normally it would
958    be read-only until libstdc++.so is processed by dl_iterate_phdr_callback
959    (on the read-write pass), after which it will be writable.  But if any loaded
960    object gets processed before libstdc++.so, it will attempt to update the
961    data cache, which will still be read-only, and cause a seg fault.  Hence
962    we need a special function, called before dl_iterate_phdr_callback, that
963    will make the data cache writable.  */
964 
965 static void
change_protections_on_phdr_cache(int protection_flag)966 change_protections_on_phdr_cache (int protection_flag)
967 {
968   char * low_address = (char *) &(vtv_sect_info_cache);
969   size_t cache_size = MAX_ENTRIES * sizeof (struct sect_hdr_data);
970 
971   low_address = (char *) ((uintptr_t) low_address & ~(VTV_PAGE_SIZE - 1));
972 
973   if (mprotect ((void *) low_address, cache_size, protection_flag) == -1)
974     VTV_error ();
975 }
976 
977 /* Unprotect all the vtable map vars and other side data that is used
978    to keep the core hash_map data. All of these data have been put
979    into relro sections */
980 
981 static void
vtv_unprotect_vtable_vars(void)982 vtv_unprotect_vtable_vars (void)
983 {
984   int mprotect_flags;
985 
986   mprotect_flags = PROT_READ | PROT_WRITE;
987   change_protections_on_phdr_cache (mprotect_flags);
988 #if defined (__CYGWIN__) || defined (__MINGW32__)
989   iterate_modules ((void *) &mprotect_flags);
990 #else
991   dl_iterate_phdr (dl_iterate_phdr_callback, (void *) &mprotect_flags);
992 #endif
993 }
994 
995 /* Protect all the vtable map vars and other side data that is used
996    to keep the core hash_map data. All of these data have been put
997    into relro sections */
998 
999 static void
vtv_protect_vtable_vars(void)1000 vtv_protect_vtable_vars (void)
1001 {
1002   int mprotect_flags;
1003 
1004   mprotect_flags = PROT_READ;
1005 #if defined (__CYGWIN__) || defined (__MINGW32__)
1006   iterate_modules ((void *) &mprotect_flags);
1007 #else
1008   dl_iterate_phdr (dl_iterate_phdr_callback, (void *) &mprotect_flags);
1009 #endif
1010   change_protections_on_phdr_cache (mprotect_flags);
1011 }
1012 
1013 #ifndef __GTHREAD_MUTEX_INIT
1014 static void
initialize_change_permissions_mutexes()1015 initialize_change_permissions_mutexes ()
1016 {
1017   __GTHREAD_MUTEX_INIT_FUNCTION (&change_permissions_lock);
1018 }
1019 #endif
1020 
1021 /*  Variables needed for getting the statistics about the hashtable set.  */
1022 #if HASHTABLE_STATS
1023 _AtomicStatCounter stat_contains = 0;
1024 _AtomicStatCounter stat_insert = 0;
1025 _AtomicStatCounter stat_resize = 0;
1026 _AtomicStatCounter stat_create = 0;
1027 _AtomicStatCounter stat_probes_in_non_trivial_set = 0;
1028 _AtomicStatCounter stat_contains_size0 = 0;
1029 _AtomicStatCounter stat_contains_size1 = 0;
1030 _AtomicStatCounter stat_contains_size2 = 0;
1031 _AtomicStatCounter stat_contains_size3 = 0;
1032 _AtomicStatCounter stat_contains_size4 = 0;
1033 _AtomicStatCounter stat_contains_size5 = 0;
1034 _AtomicStatCounter stat_contains_size6 = 0;
1035 _AtomicStatCounter stat_contains_size7 = 0;
1036 _AtomicStatCounter stat_contains_size8 = 0;
1037 _AtomicStatCounter stat_contains_size9 = 0;
1038 _AtomicStatCounter stat_contains_size10 = 0;
1039 _AtomicStatCounter stat_contains_size11 = 0;
1040 _AtomicStatCounter stat_contains_size12 = 0;
1041 _AtomicStatCounter stat_contains_size13_or_more = 0;
1042 _AtomicStatCounter stat_contains_sizes = 0;
1043 _AtomicStatCounter stat_grow_from_size0_to_1 = 0;
1044 _AtomicStatCounter stat_grow_from_size1_to_2 = 0;
1045 _AtomicStatCounter stat_double_the_number_of_buckets = 0;
1046 _AtomicStatCounter stat_insert_found_hash_collision = 0;
1047 _AtomicStatCounter stat_contains_in_non_trivial_set = 0;
1048 _AtomicStatCounter stat_insert_key_that_was_already_present = 0;
1049 #endif
1050 /* Record statistics about the hash table sets, for debugging.  */
1051 
1052 static void
log_set_stats(void)1053 log_set_stats (void)
1054 {
1055 #if HASHTABLE_STATS
1056       if (set_log_fd == -1)
1057 	set_log_fd = __vtv_open_log ("vtv_set_stats.log");
1058 
1059       __vtv_add_to_log (set_log_fd, "---\n%s\n",
1060 			insert_only_hash_tables_stats().c_str());
1061 #endif
1062 }
1063 
1064 /* Change the permissions on all the pages we have allocated for the
1065    data sets and all the ".vtable_map_var" sections in memory (which
1066    contain our vtable map variables).  PERM indicates whether to make
1067    the permissions read-only or read-write.  */
1068 
1069 extern "C" /* This is only being applied to __VLTChangePermission*/
1070 void
__VLTChangePermission(int perm)1071 __VLTChangePermission (int perm)
1072 {
1073   if (debug_functions)
1074     {
1075       if (perm == __VLTP_READ_WRITE)
1076 	fprintf (stdout, "Changing VLT permissions to Read-Write.\n");
1077       else if (perm == __VLTP_READ_ONLY)
1078 	fprintf (stdout, "Changing VLT permissions to Read-Only.\n");
1079 
1080       else
1081 	fprintf (stdout, "Unrecognized permissions value: %d\n", perm);
1082     }
1083 
1084 #ifndef __GTHREAD_MUTEX_INIT
1085   static __gthread_once_t mutex_once VTV_PROTECTED_VAR = __GTHREAD_ONCE_INIT;
1086 
1087   __gthread_once (&mutex_once, initialize_change_permissions_mutexes);
1088 #endif
1089 
1090   /* Ordering of these unprotect/protect calls is very important.
1091      You first need to unprotect all the map vars and side
1092      structures before you do anything with the core data
1093      structures (hash_maps) */
1094 
1095   if (perm == __VLTP_READ_WRITE)
1096     {
1097       /* TODO: Need to revisit this code for dlopen. It most probably
1098          is not unlocking the protected vtable vars after for load
1099          module that is not the first load module.  */
1100       __gthread_mutex_lock (&change_permissions_lock);
1101 
1102       vtv_unprotect_vtable_vars ();
1103       __vtv_malloc_init ();
1104       __vtv_malloc_unprotect ();
1105 
1106     }
1107   else if (perm == __VLTP_READ_ONLY)
1108     {
1109       if (debug_hash)
1110         log_set_stats();
1111 
1112       __vtv_malloc_protect ();
1113       vtv_protect_vtable_vars ();
1114 
1115       __gthread_mutex_unlock (&change_permissions_lock);
1116     }
1117 }
1118 
1119 /* This is the memory allocator used to create the hash table that
1120    maps from vtable map variable name to the data set that vtable map
1121    variable should point to.  This is part of our vtable map variable
1122    symbol resolution, which is necessary because the same vtable map
1123    variable may be created by multiple compilation units and we need a
1124    method to make sure that all vtable map variables for a particular
1125    class point to the same data set at runtime.  */
1126 
1127 struct insert_only_hash_map_allocator
1128   {
1129     /* N is the number of bytes to allocate.  */
1130     void *
allocinsert_only_hash_map_allocator1131     alloc (size_t n) const
1132     {
1133       return __vtv_malloc (n);
1134     }
1135 
1136     /* P points to the memory to be deallocated; N is the number of
1137        bytes to deallocate.  */
1138     void
deallocinsert_only_hash_map_allocator1139     dealloc (void *p, size_t) const
1140     {
1141       __vtv_free (p);
1142     }
1143   };
1144 
1145 /* Explicitly instantiate this class since this file is compiled with
1146    -fno-implicit-templates.  These are for the hash table that is used
1147    to do vtable map variable symbol resolution.  */
1148 template class insert_only_hash_map <vtv_set_handle *,
1149 				     insert_only_hash_map_allocator >;
1150 typedef insert_only_hash_map <vtv_set_handle *,
1151                               insert_only_hash_map_allocator > s2s;
1152 typedef const s2s::key_type  vtv_symbol_key;
1153 
1154 static s2s * vtv_symbol_unification_map VTV_PROTECTED_VAR = NULL;
1155 
1156 const unsigned long SET_HANDLE_HANDLE_BIT = 0x2;
1157 
1158 /* In the case where a vtable map variable is the only instance of the
1159    variable we have seen, it points directly to the set of valid
1160    vtable pointers.  All subsequent instances of the 'same' vtable map
1161    variable point to the first vtable map variable.  This function,
1162    given a vtable map variable PTR, checks a bit to see whether it's
1163    pointing directly to the data set or to the first vtable map
1164    variable.  */
1165 
1166 static inline bool
is_set_handle_handle(void * ptr)1167 is_set_handle_handle (void * ptr)
1168 {
1169   return ((uintptr_t) ptr & SET_HANDLE_HANDLE_BIT)
1170                                                       == SET_HANDLE_HANDLE_BIT;
1171 }
1172 
1173 /* Returns the actual pointer value of a vtable map variable, PTR (see
1174    comments for is_set_handle_handle for more details).  */
1175 
1176 static inline vtv_set_handle *
ptr_from_set_handle_handle(void * ptr)1177 ptr_from_set_handle_handle (void * ptr)
1178 {
1179   return (vtv_set_handle *) ((uintptr_t) ptr & ~SET_HANDLE_HANDLE_BIT);
1180 }
1181 
1182 /* Given a vtable map variable, PTR, this function sets the bit that
1183    says this is the second (or later) instance of a vtable map
1184    variable.  */
1185 
1186 static inline vtv_set_handle_handle
set_handle_handle(vtv_set_handle * ptr)1187 set_handle_handle (vtv_set_handle * ptr)
1188 {
1189   return (vtv_set_handle_handle) ((uintptr_t) ptr | SET_HANDLE_HANDLE_BIT);
1190 }
1191 
1192 static inline void
register_set_common(void ** set_handle_ptr,size_t num_args,void ** vtable_ptr_array,bool debug)1193 register_set_common (void **set_handle_ptr, size_t num_args,
1194                      void **vtable_ptr_array, bool debug)
1195 {
1196   /* Now figure out what pointer to use for the set pointer, for the
1197      inserts.  */
1198   vtv_set_handle *handle_ptr = (vtv_set_handle *) set_handle_ptr;
1199 
1200   if (debug)
1201     VTV_DEBUG_ASSERT (vtv_symbol_unification_map != NULL);
1202 
1203   if (!is_set_handle_handle (*set_handle_ptr))
1204     handle_ptr = (vtv_set_handle *) set_handle_ptr;
1205   else
1206     handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
1207 
1208   /* Now we've got the set and it's initialized, add the vtable
1209      pointers.  */
1210   for (size_t index = 0; index < num_args; ++index)
1211     {
1212       int_vptr vtbl_ptr = (int_vptr) vtable_ptr_array[index];
1213       vtv_sets::insert (vtbl_ptr, handle_ptr);
1214     }
1215 }
1216 
1217 static inline void
register_pair_common(void ** set_handle_ptr,const void * vtable_ptr,const char * set_symbol_name,const char * vtable_name,bool debug)1218 register_pair_common (void **set_handle_ptr, const void *vtable_ptr,
1219                       const char *set_symbol_name, const char *vtable_name,
1220                       bool debug)
1221 {
1222   /* Now we've got the set and it's initialized, add the vtable
1223      pointer (assuming that it's not NULL...It may be NULL, as we may
1224      have called this function merely to initialize the set
1225      pointer).  */
1226   int_vptr vtbl_ptr = (int_vptr) vtable_ptr;
1227   if (vtbl_ptr)
1228     {
1229       vtv_set_handle *handle_ptr = (vtv_set_handle *) set_handle_ptr;
1230       if (debug)
1231         VTV_DEBUG_ASSERT (vtv_symbol_unification_map != NULL);
1232       if (!is_set_handle_handle (*set_handle_ptr))
1233         handle_ptr = (vtv_set_handle *) set_handle_ptr;
1234       else
1235         handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
1236 
1237       vtv_sets::insert (vtbl_ptr, handle_ptr);
1238     }
1239 
1240   if (debug && debug_init)
1241     {
1242       if (init_log_fd == -1)
1243         init_log_fd = __vtv_open_log("vtv_init.log");
1244 
1245       __vtv_add_to_log(init_log_fd,
1246 		       "Registered %s : %s (%p) 2 level deref = %s\n",
1247 		       set_symbol_name, vtable_name, vtbl_ptr,
1248 		       is_set_handle_handle(*set_handle_ptr) ? "yes" : "no" );
1249     }
1250 }
1251 
1252 /* This routine initializes a set handle to a vtable set. It makes
1253    sure that there is only one set handle for a particular set by
1254    using a map from set name to pointer to set handle. Since there
1255    will be multiple copies of the pointer to the set handle (one per
1256    compilation unit that uses it), it makes sure to initialize all the
1257    pointers to the set handle so that the set handle is unique. To
1258    make this a little more efficient and avoid a level of indirection
1259    in some cases, the first pointer to handle for a particular handle
1260    becomes the handle itself and the other pointers will point to the
1261    set handle.  This is the debug version of this function, so it
1262    outputs extra debugging messages and logging.  SET_HANDLE_PTR is
1263    the address of the vtable map variable, SET_SYMBOL_KEY is the hash
1264    table key (containing the name of the map variable and the hash
1265    value) and SIZE_HINT is a guess for the best initial size for the
1266    set of vtable pointers that SET_HANDLE_POINTER will point to.  */
1267 
1268 static inline void
init_set_symbol_debug(void ** set_handle_ptr,const void * set_symbol_key,size_t size_hint)1269 init_set_symbol_debug (void **set_handle_ptr, const void *set_symbol_key,
1270                        size_t size_hint)
1271 {
1272   VTV_DEBUG_ASSERT (set_handle_ptr);
1273 
1274   if (vtv_symbol_unification_map == NULL)
1275     {
1276       /* TODO:  For now we have chosen 1024, but we need to come up with a
1277          better initial size for this.  */
1278       vtv_symbol_unification_map = s2s::create (1024);
1279       VTV_DEBUG_ASSERT(vtv_symbol_unification_map);
1280     }
1281 
1282   vtv_set_handle *handle_ptr = (vtv_set_handle *) set_handle_ptr;
1283   vtv_symbol_key *symbol_key_ptr = (vtv_symbol_key *) set_symbol_key;
1284 
1285   const s2s::value_type * map_value_ptr =
1286                               vtv_symbol_unification_map->get (symbol_key_ptr);
1287   char buffer[200];
1288   if (map_value_ptr == NULL)
1289     {
1290       if (*handle_ptr != NULL)
1291         {
1292           snprintf (buffer, sizeof (buffer),
1293                     "*** Found non-NULL local set ptr %p missing for symbol"
1294                     " %.*s",
1295                     *handle_ptr, symbol_key_ptr->n, symbol_key_ptr->bytes);
1296           __vtv_log_verification_failure (buffer, true);
1297           VTV_DEBUG_ASSERT (0);
1298         }
1299     }
1300   else if (*handle_ptr != NULL &&
1301            (handle_ptr != *map_value_ptr &&
1302             ptr_from_set_handle_handle (*handle_ptr) != *map_value_ptr))
1303     {
1304       VTV_DEBUG_ASSERT (*map_value_ptr != NULL);
1305       snprintf (buffer, sizeof(buffer),
1306                 "*** Found diffence between local set ptr %p and set ptr %p"
1307                 "for symbol %.*s",
1308                 *handle_ptr, *map_value_ptr,
1309                 symbol_key_ptr->n, symbol_key_ptr->bytes);
1310       __vtv_log_verification_failure (buffer, true);
1311       VTV_DEBUG_ASSERT (0);
1312     }
1313   else if (*handle_ptr == NULL)
1314     {
1315       /* Execution should not reach this point.  */
1316     }
1317 
1318   if (*handle_ptr != NULL)
1319     {
1320       if (!is_set_handle_handle (*set_handle_ptr))
1321         handle_ptr = (vtv_set_handle *) set_handle_ptr;
1322       else
1323         handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
1324       vtv_sets::resize (size_hint, handle_ptr);
1325       return;
1326     }
1327 
1328   VTV_DEBUG_ASSERT (*handle_ptr == NULL);
1329   if (map_value_ptr != NULL)
1330     {
1331       if (*map_value_ptr == handle_ptr)
1332         vtv_sets::resize (size_hint, *map_value_ptr);
1333       else
1334         {
1335           /* The one level handle to the set already exists. So, we
1336              are adding one level of indirection here and we will
1337              store a pointer to the one level handle here.  */
1338 
1339           vtv_set_handle_handle * handle_handle_ptr =
1340                                            (vtv_set_handle_handle *)handle_ptr;
1341           *handle_handle_ptr = set_handle_handle(*map_value_ptr);
1342           VTV_DEBUG_ASSERT(*handle_handle_ptr != NULL);
1343 
1344           /* The handle can itself be NULL if the set has only
1345              been initiazlied with size hint == 1. */
1346           vtv_sets::resize (size_hint, *map_value_ptr);
1347         }
1348     }
1349   else
1350     {
1351       /* We will create a new set. So, in this case handle_ptr is the
1352          one level pointer to the set handle.  Create copy of map name
1353          in case the memory where this comes from gets unmapped by
1354          dlclose.  */
1355       size_t map_key_len = symbol_key_ptr->n + sizeof (vtv_symbol_key);
1356       void *map_key = __vtv_malloc (map_key_len);
1357 
1358       memcpy (map_key, symbol_key_ptr, map_key_len);
1359 
1360       s2s::value_type *value_ptr;
1361       vtv_symbol_unification_map =
1362         vtv_symbol_unification_map->find_or_add_key ((vtv_symbol_key *)map_key,
1363                                                      &value_ptr);
1364       *value_ptr = handle_ptr;
1365 
1366       /*  TODO: We should verify the return value. */
1367       vtv_sets::create (size_hint, handle_ptr);
1368       VTV_DEBUG_ASSERT (size_hint <= 1 || *handle_ptr != NULL);
1369     }
1370 
1371   if (debug_init)
1372     {
1373       if (init_log_fd == -1)
1374         init_log_fd = __vtv_open_log ("vtv_init.log");
1375 
1376       __vtv_add_to_log (init_log_fd,
1377 			"Init handle:%p for symbol:%.*s hash:%u size_hint:%lu"
1378 			"number of symbols:%lu \n",
1379 			set_handle_ptr, symbol_key_ptr->n,
1380 			symbol_key_ptr->bytes, symbol_key_ptr->hash, size_hint,
1381 			vtv_symbol_unification_map->size ());
1382     }
1383 }
1384 
1385 
1386 /* This routine initializes a set handle to a vtable set. It makes
1387    sure that there is only one set handle for a particular set by
1388    using a map from set name to pointer to set handle. Since there
1389    will be multiple copies of the pointer to the set handle (one per
1390    compilation unit that uses it), it makes sure to initialize all the
1391    pointers to the set handle so that the set handle is unique. To
1392    make this a little more efficient and avoid a level of indirection
1393    in some cases, the first pointer to handle for a particular handle
1394    becomes the handle itself and the other pointers will point to the
1395    set handle.  This is the debug version of this function, so it
1396    outputs extra debugging messages and logging.  SET_HANDLE_PTR is
1397    the address of the vtable map variable, SET_SYMBOL_KEY is the hash
1398    table key (containing the name of the map variable and the hash
1399    value) and SIZE_HINT is a guess for the best initial size for the
1400    set of vtable pointers that SET_HANDLE_POINTER will point to.  */
1401 
1402 void
__VLTRegisterSetDebug(void ** set_handle_ptr,const void * set_symbol_key,size_t size_hint,size_t num_args,void ** vtable_ptr_array)1403 __VLTRegisterSetDebug (void **set_handle_ptr, const void *set_symbol_key,
1404                        size_t size_hint, size_t num_args,
1405                        void **vtable_ptr_array)
1406 {
1407   unsigned long long start = get_cycle_count ();
1408   increment_num_calls (&num_calls_to_regset);
1409 
1410   VTV_DEBUG_ASSERT(set_handle_ptr != NULL);
1411   init_set_symbol_debug (set_handle_ptr, set_symbol_key, size_hint);
1412 
1413   register_set_common (set_handle_ptr, num_args, vtable_ptr_array, true);
1414 
1415   accumulate_cycle_count (&regset_cycles, start);
1416 }
1417 
1418 /* This function takes a the address of a vtable map variable
1419    (SET_HANDLE_PTR), a VTABLE_PTR to add to the data set, the name of
1420    the vtable map variable (SET_SYMBOL_NAME) and the name of the
1421    vtable (VTABLE_NAME) being pointed to.  If the vtable map variable
1422    is NULL it creates a new data set and initializes the variable,
1423    otherwise it uses our symbol unification to find the right data
1424    set; in either case it then adds the vtable pointer to the set.
1425    The other two parameters are used for debugging information.  */
1426 
1427 void
__VLTRegisterPairDebug(void ** set_handle_ptr,const void * set_symbol_key,size_t size_hint,const void * vtable_ptr,const char * set_symbol_name,const char * vtable_name)1428 __VLTRegisterPairDebug (void **set_handle_ptr, const  void *set_symbol_key,
1429                         size_t size_hint, const void *vtable_ptr,
1430                         const char *set_symbol_name, const char *vtable_name)
1431 {
1432   unsigned long long start = get_cycle_count ();
1433   increment_num_calls (&num_calls_to_regpair);
1434 
1435   VTV_DEBUG_ASSERT(set_handle_ptr != NULL);
1436   init_set_symbol_debug (set_handle_ptr, set_symbol_key, size_hint);
1437 
1438   register_pair_common (set_handle_ptr, vtable_ptr, set_symbol_name, vtable_name,
1439                         true);
1440 
1441   accumulate_cycle_count (&regpair_cycles, start);
1442 }
1443 
1444 
1445 /* This is the debug version of the verification function.  It takes
1446    the address of a vtable map variable (SET_HANDLE_PTR) and a
1447    VTABLE_PTR to validate, as well as the name of the vtable map
1448    variable (SET_SYMBOL_NAME) and VTABLE_NAME, which are used for
1449    debugging messages.  It checks to see if VTABLE_PTR is in the set
1450    pointed to by SET_HANDLE_PTR.  If so, it returns VTABLE_PTR,
1451    otherwise it calls __vtv_verify_fail, which usually logs error
1452    messages and calls abort.  */
1453 
1454 const void *
__VLTVerifyVtablePointerDebug(void ** set_handle_ptr,const void * vtable_ptr,const char * set_symbol_name,const char * vtable_name)1455 __VLTVerifyVtablePointerDebug (void **set_handle_ptr, const void *vtable_ptr,
1456                                const char *set_symbol_name,
1457 			       const char *vtable_name)
1458 {
1459   unsigned long long start = get_cycle_count ();
1460   VTV_DEBUG_ASSERT (set_handle_ptr != NULL && *set_handle_ptr != NULL);
1461   int_vptr vtbl_ptr = (int_vptr) vtable_ptr;
1462 
1463   increment_num_calls (&num_calls_to_verify_vtable);
1464   vtv_set_handle *handle_ptr;
1465   if (!is_set_handle_handle (*set_handle_ptr))
1466     handle_ptr = (vtv_set_handle *) set_handle_ptr;
1467   else
1468     handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
1469 
1470   if (vtv_sets::contains (vtbl_ptr, handle_ptr))
1471     {
1472       if (debug_verify_vtable)
1473         {
1474           if (verify_vtable_log_fd == -1)
1475             __vtv_open_log ("vtv_verify_vtable.log");
1476           __vtv_add_to_log (verify_vtable_log_fd,
1477 			    "Verified %s %s value = %p\n",
1478 			    set_symbol_name, vtable_name, vtable_ptr);
1479         }
1480     }
1481   else
1482     {
1483       /* We failed to find the vtable pointer in the set of valid
1484 	 pointers.  Log the error data and call the failure
1485 	 function.  */
1486       snprintf (debug_log_message, sizeof (debug_log_message),
1487 		"Looking for %s in %s\n", vtable_name, set_symbol_name);
1488       __vtv_verify_fail_debug (set_handle_ptr, vtable_ptr, debug_log_message);
1489 
1490       /* Normally __vtv_verify_fail_debug will call abort, so we won't
1491          execute the return below.  If we get this far, the assumption
1492          is that the programmer has replaced __vtv_verify_fail_debug
1493          with some kind of secondary verification AND this secondary
1494          verification succeeded, so the vtable pointer is valid.  */
1495     }
1496   accumulate_cycle_count (&verify_vtable_cycles, start);
1497 
1498   return vtable_ptr;
1499 }
1500 
1501 /* This routine initializes a set handle to a vtable set. It makes
1502    sure that there is only one set handle for a particular set by
1503    using a map from set name to pointer to set handle. Since there
1504    will be multiple copies of the pointer to the set handle (one per
1505    compilation unit that uses it), it makes sure to initialize all the
1506    pointers to the set handle so that the set handle is unique. To
1507    make this a little more efficient and avoid a level of indirection
1508    in some cases, the first pointer to handle for a particular handle
1509    becomes the handle itself and the other pointers will point to the
1510    set handle.  SET_HANDLE_PTR is the address of the vtable map
1511    variable, SET_SYMBOL_KEY is the hash table key (containing the name
1512    of the map variable and the hash value) and SIZE_HINT is a guess
1513    for the best initial size for the set of vtable pointers that
1514    SET_HANDLE_POINTER will point to.*/
1515 
1516 static inline void
init_set_symbol(void ** set_handle_ptr,const void * set_symbol_key,size_t size_hint)1517 init_set_symbol (void **set_handle_ptr, const void *set_symbol_key,
1518                  size_t size_hint)
1519 {
1520   vtv_set_handle *handle_ptr = (vtv_set_handle *) set_handle_ptr;
1521 
1522   if (*handle_ptr != NULL)
1523     {
1524       if (!is_set_handle_handle (*set_handle_ptr))
1525         handle_ptr = (vtv_set_handle *) set_handle_ptr;
1526       else
1527         handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
1528       vtv_sets::resize (size_hint, handle_ptr);
1529       return;
1530     }
1531 
1532   if (vtv_symbol_unification_map == NULL)
1533     vtv_symbol_unification_map = s2s::create (1024);
1534 
1535   vtv_symbol_key *symbol_key_ptr = (vtv_symbol_key *) set_symbol_key;
1536   const s2s::value_type *map_value_ptr =
1537                               vtv_symbol_unification_map->get (symbol_key_ptr);
1538 
1539   if (map_value_ptr != NULL)
1540     {
1541       if (*map_value_ptr == handle_ptr)
1542         vtv_sets::resize (size_hint, *map_value_ptr);
1543       else
1544         {
1545           /* The one level handle to the set already exists. So, we
1546              are adding one level of indirection here and we will
1547              store a pointer to the one level pointer here.  */
1548           vtv_set_handle_handle *handle_handle_ptr =
1549                                           (vtv_set_handle_handle *) handle_ptr;
1550           *handle_handle_ptr = set_handle_handle (*map_value_ptr);
1551           vtv_sets::resize (size_hint, *map_value_ptr);
1552         }
1553     }
1554   else
1555     {
1556       /* We will create a new set. So, in this case handle_ptr is the
1557          one level pointer to the set handle.  Create copy of map name
1558          in case the memory where this comes from gets unmapped by
1559          dlclose.  */
1560       size_t map_key_len = symbol_key_ptr->n + sizeof (vtv_symbol_key);
1561       void * map_key = __vtv_malloc (map_key_len);
1562       memcpy (map_key, symbol_key_ptr, map_key_len);
1563 
1564       s2s::value_type * value_ptr;
1565       vtv_symbol_unification_map =
1566         vtv_symbol_unification_map->find_or_add_key ((vtv_symbol_key *)map_key,
1567                                                      &value_ptr);
1568 
1569       *value_ptr = handle_ptr;
1570 
1571       /* TODO: We should verify the return value.  */
1572       vtv_sets::create (size_hint, handle_ptr);
1573     }
1574 }
1575 
1576 /* This routine initializes a set handle to a vtable set. It makes
1577    sure that there is only one set handle for a particular set by
1578    using a map from set name to pointer to set handle. Since there
1579    will be multiple copies of the pointer to the set handle (one per
1580    compilation unit that uses it), it makes sure to initialize all the
1581    pointers to the set handle so that the set handle is unique. To
1582    make this a little more efficient and avoid a level of indirection
1583    in some cases, the first pointer to handle for a particular handle
1584    becomes the handle itself and the other pointers will point to the
1585    set handle.  SET_HANDLE_PTR is the address of the vtable map
1586    variable, SET_SYMBOL_KEY is the hash table key (containing the name
1587    of the map variable and the hash value) and SIZE_HINT is a guess
1588    for the best initial size for the set of vtable pointers that
1589    SET_HANDLE_POINTER will point to.*/
1590 
1591 
1592 void
__VLTRegisterSet(void ** set_handle_ptr,const void * set_symbol_key,size_t size_hint,size_t num_args,void ** vtable_ptr_array)1593 __VLTRegisterSet (void **set_handle_ptr, const void *set_symbol_key,
1594                   size_t size_hint, size_t num_args, void **vtable_ptr_array)
1595 {
1596   unsigned long long start = get_cycle_count ();
1597   increment_num_calls (&num_calls_to_regset);
1598 
1599   init_set_symbol (set_handle_ptr, set_symbol_key, size_hint);
1600   register_set_common (set_handle_ptr, num_args, vtable_ptr_array, false);
1601 
1602   accumulate_cycle_count (&regset_cycles, start);
1603 }
1604 
1605 
1606 
1607 /* This function takes a the address of a vtable map variable
1608    (SET_HANDLE_PTR) and a VTABLE_PTR.  If the vtable map variable is
1609    NULL it creates a new data set and initializes the variable,
1610    otherwise it uses our symbol unification to find the right data
1611    set; in either case it then adds the vtable pointer to the set.  */
1612 
1613 void
__VLTRegisterPair(void ** set_handle_ptr,const void * set_symbol_key,size_t size_hint,const void * vtable_ptr)1614 __VLTRegisterPair (void **set_handle_ptr, const  void *set_symbol_key,
1615                    size_t size_hint, const void *vtable_ptr)
1616 {
1617   unsigned long long start = get_cycle_count ();
1618   increment_num_calls (&num_calls_to_regpair);
1619 
1620   init_set_symbol (set_handle_ptr, set_symbol_key, size_hint);
1621   register_pair_common (set_handle_ptr, vtable_ptr, NULL, NULL,  false);
1622 
1623   accumulate_cycle_count (&regpair_cycles, start);
1624 }
1625 
1626 /* This is the main verification function.  It takes the address of a
1627    vtable map variable (SET_HANDLE_PTR) and a VTABLE_PTR to validate.
1628    It checks to see if VTABLE_PTR is in the set pointed to by
1629    SET_HANDLE_PTR.  If so, it returns VTABLE_PTR, otherwise it calls
1630    __vtv_verify_fail, which usually logs error messages and calls
1631    abort.  Since this function gets called VERY frequently, it is
1632    important for it to be as efficient as possible.  */
1633 
1634 const void *
__VLTVerifyVtablePointer(void ** set_handle_ptr,const void * vtable_ptr)1635 __VLTVerifyVtablePointer (void ** set_handle_ptr, const void * vtable_ptr)
1636 {
1637   unsigned long long start = get_cycle_count ();
1638   int_vptr vtbl_ptr = (int_vptr) vtable_ptr;
1639 
1640   vtv_set_handle *handle_ptr;
1641   increment_num_calls (&num_calls_to_verify_vtable);
1642   if (!is_set_handle_handle (*set_handle_ptr))
1643     handle_ptr = (vtv_set_handle *) set_handle_ptr;
1644   else
1645     handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
1646 
1647   if (!vtv_sets::contains (vtbl_ptr, handle_ptr))
1648     {
1649       __vtv_verify_fail ((void **) handle_ptr, vtable_ptr);
1650       /* Normally __vtv_verify_fail will call abort, so we won't
1651          execute the return below.  If we get this far, the assumption
1652          is that the programmer has replaced __vtv_verify_fail with
1653          some kind of secondary verification AND this secondary
1654          verification succeeded, so the vtable pointer is valid.  */
1655     }
1656   accumulate_cycle_count (&verify_vtable_cycles, start);
1657 
1658   return vtable_ptr;
1659 }
1660 
1661 static int page_count_2 = 0;
1662 
1663 #if !defined (__CYGWIN__) && !defined (__MINGW32__)
1664 static int
dl_iterate_phdr_count_pages(struct dl_phdr_info * info,size_t unused,void * data)1665 dl_iterate_phdr_count_pages (struct dl_phdr_info *info,
1666                              size_t unused __attribute__ ((__unused__)),
1667                              void *data)
1668 {
1669   int *mprotect_flags = (int *) data;
1670   off_t map_sect_offset = 0;
1671   ElfW (Word) map_sect_len = 0;
1672   const char *map_sect_name = VTV_PROTECTED_VARS_SECTION;
1673 
1674   /* Check to see if this is the record for the Linux Virtual Dynamic
1675      Shared Object (linux-vdso.so.1), which exists only in memory (and
1676      therefore cannot be read from disk).  */
1677 
1678   if (strcmp (info->dlpi_name, "linux-vdso.so.1") == 0)
1679     return 0;
1680 
1681   if (strlen (info->dlpi_name) == 0
1682       && info->dlpi_addr != 0)
1683     return 0;
1684 
1685   read_section_offset_and_length (info, map_sect_name, *mprotect_flags,
1686                                  &map_sect_offset, &map_sect_len);
1687 
1688   /* See if we actually found the section.  */
1689   if (map_sect_len)
1690     page_count_2 += (map_sect_len + VTV_PAGE_SIZE - 1) / VTV_PAGE_SIZE;
1691 
1692   return 0;
1693 }
1694 #endif
1695 
1696 static void
count_all_pages(void)1697 count_all_pages (void)
1698 {
1699   int mprotect_flags;
1700 
1701   mprotect_flags = PROT_READ;
1702   page_count_2 = 0;
1703 
1704 #if defined (__CYGWIN__) || defined (__MINGW32__)
1705   iterate_modules ((void *) &mprotect_flags);
1706 #else
1707   dl_iterate_phdr (dl_iterate_phdr_count_pages, (void *) &mprotect_flags);
1708 #endif
1709   page_count_2 += __vtv_count_mmapped_pages ();
1710 }
1711 
1712 void
__VLTDumpStats(void)1713 __VLTDumpStats (void)
1714 {
1715   int log_fd = __vtv_open_log ("vtv-runtime-stats.log");
1716 
1717   if (log_fd != -1)
1718     {
1719       count_all_pages ();
1720       __vtv_add_to_log (log_fd,
1721 			"Calls: mprotect (%d)  regset (%d) regpair (%d)"
1722 			" verify_vtable (%d)\n",
1723 			num_calls_to_mprotect, num_calls_to_regset,
1724 			num_calls_to_regpair, num_calls_to_verify_vtable);
1725       __vtv_add_to_log (log_fd,
1726 			"Cycles: mprotect (%lld) regset (%lld) "
1727 			"regpair (%lld) verify_vtable (%lld)\n",
1728 			mprotect_cycles, regset_cycles, regpair_cycles,
1729 			verify_vtable_cycles);
1730       __vtv_add_to_log (log_fd,
1731 			"Pages protected (1): %d\n", num_pages_protected);
1732       __vtv_add_to_log (log_fd, "Pages protected (2): %d\n", page_count_2);
1733 
1734       close (log_fd);
1735     }
1736 }
1737 
1738 /* This function is called from __VLTVerifyVtablePointerDebug; it
1739    sends as much debugging information as it can to the error log
1740    file, then calls __vtv_verify_fail.  SET_HANDLE_PTR is the pointer
1741    to the set of valid vtable pointers, VTBL_PTR is the pointer that
1742    was not found in the set, and DEBUG_MSG is the message to be
1743    written to the log file before failing. n */
1744 
1745 void
__vtv_verify_fail_debug(void ** set_handle_ptr,const void * vtbl_ptr,const char * debug_msg)1746 __vtv_verify_fail_debug (void **set_handle_ptr, const void *vtbl_ptr,
1747                          const char *debug_msg)
1748 {
1749   __vtv_log_verification_failure (debug_msg, false);
1750 
1751   /* Call the public interface in case it has been overwritten by
1752      user.  */
1753   __vtv_verify_fail (set_handle_ptr, vtbl_ptr);
1754 
1755   __vtv_log_verification_failure ("Returned from __vtv_verify_fail."
1756                      " Secondary verification succeeded.\n", false);
1757 }
1758 
1759 /* This function calls __fortify_fail with a FAILURE_MSG and then
1760    calls abort.  */
1761 
1762 void
__vtv_really_fail(const char * failure_msg)1763 __vtv_really_fail (const char *failure_msg)
1764 {
1765   __fortify_fail (failure_msg);
1766 
1767   /* We should never get this far; __fortify_fail calls __libc_message
1768      which prints out a back trace and a memory dump and then is
1769      supposed to call abort, but let's play it safe anyway and call abort
1770      ourselves.  */
1771   abort ();
1772 }
1773 
1774 /* This function takes an error MSG, a vtable map variable
1775    (DATA_SET_PTR) and a vtable pointer (VTBL_PTR).  It is called when
1776    an attempt to verify VTBL_PTR with the set pointed to by
1777    DATA_SET_PTR failed.  It outputs a failure message with the
1778    addresses involved, and calls __vtv_really_fail.  */
1779 
1780 static void
vtv_fail(const char * msg,void ** data_set_ptr,const void * vtbl_ptr)1781 vtv_fail (const char *msg, void **data_set_ptr, const void *vtbl_ptr)
1782 {
1783   char buffer[128];
1784   int buf_len;
1785   const char *format_str =
1786                  "*** Unable to verify vtable pointer (%p) in set (%p) *** \n";
1787 
1788   snprintf (buffer, sizeof (buffer), format_str, vtbl_ptr,
1789             is_set_handle_handle(*data_set_ptr) ?
1790               ptr_from_set_handle_handle (*data_set_ptr) :
1791 	      *data_set_ptr);
1792   buf_len = strlen (buffer);
1793   /*  Send this to to stderr.  */
1794   write (2, buffer, buf_len);
1795 
1796 #ifndef VTV_NO_ABORT
1797     __vtv_really_fail (msg);
1798 #endif
1799 }
1800 
1801 /* Send information about what we were trying to do when verification
1802    failed to the error log, then call vtv_fail.  This function can be
1803    overwritten/replaced by the user, to implement a secondary
1804    verification function instead.  DATA_SET_PTR is the vtable map
1805    variable used for the failed verification, and VTBL_PTR is the
1806    vtable pointer that was not found in the set.  */
1807 
1808 void
__vtv_verify_fail(void ** data_set_ptr,const void * vtbl_ptr)1809 __vtv_verify_fail (void **data_set_ptr, const void *vtbl_ptr)
1810 {
1811   char log_msg[256];
1812   snprintf (log_msg, sizeof (log_msg), "Looking for vtable %p in set %p.\n",
1813             vtbl_ptr,
1814             is_set_handle_handle (*data_set_ptr) ?
1815               ptr_from_set_handle_handle (*data_set_ptr) :
1816               *data_set_ptr);
1817   __vtv_log_verification_failure (log_msg, false);
1818 
1819   const char *format_str =
1820             "*** Unable to verify vtable pointer (%p) in set (%p) *** \n";
1821   snprintf (log_msg, sizeof (log_msg), format_str, vtbl_ptr, *data_set_ptr);
1822   __vtv_log_verification_failure (log_msg, false);
1823   __vtv_log_verification_failure ("  Backtrace: \n", true);
1824 
1825   const char *fail_msg = "Potential vtable pointer corruption detected!!\n";
1826   vtv_fail (fail_msg, data_set_ptr, vtbl_ptr);
1827 }
1828