1/* Copyright (C) 2012-2013
2 Free Software Foundation
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 <http://www.gnu.org/licenses/>.  */
24
25/* This file is part of the vtable security feature implementation.
26   The vtable security feature is designed to detect when a virtual
27   call is about to be made through an invalid vtable pointer
28   (possibly due to data corruption or malicious attacks).
29
30   This file also contains the failure functions that get called when
31   a vtable pointer is not found in the data set.  Two particularly
32   important functions are __vtv_verify_fail and __vtv_really_fail.
33   They are both externally visible.  __vtv_verify_fail is defined in
34   such a way that it can be replaced by a programmer, if desired.  It
35   is the function that __VLTVerifyVtablePointer calls if it can't
36   find the pointer in the data set.  Allowing the programmer to
37   overwrite this function means that he/she can do some alternate
38   verification, including NOT failing in certain specific cases, if
39   desired.  This may be the case if the programmer has to deal wtih
40   unverified third party software, for example.  __vtv_really_fail is
41   available for the programmer to call from his version of
42   __vtv_verify_fail, if he decides the failure is real.
43
44*/
45
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49
50#if !defined (__CYGWIN__) && !defined (__MINGW32__)
51#include <execinfo.h>
52#endif
53
54#include <unistd.h>
55
56#include "vtv_utils.h"
57#include "vtv_fail.h"
58
59/* This is used to disable aborts for debugging purposes.  */
60bool vtv_no_abort = false;
61
62
63extern "C" {
64
65  /* __fortify_fail is a function in glibc that calls __libc_message,
66     causing it to print out a program termination error message
67     (including the name of the binary being terminated), a stack
68     trace where the error occurred, and a memory map dump.  Ideally
69     we would have called __libc_message directly, but that function
70     does not appear to be accessible to functions outside glibc,
71     whereas __fortify_fail is.  We call __fortify_fail from
72     __vtv_really_fail.  We looked at calling __libc_fatal, which is
73     externally accessible, but it does not do the back trace and
74     memory dump.  */
75
76  extern void __fortify_fail (const char *) __attribute__((noreturn));
77
78} /* extern "C" */
79
80const unsigned long SET_HANDLE_HANDLE_BIT = 0x2;
81
82/* Instantiate the template classes (in vtv_set.h) for our particular
83   hash table needs.  */
84typedef void * vtv_set_handle;
85typedef vtv_set_handle * vtv_set_handle_handle;
86
87static int vtv_failures_log_fd = -1;
88
89/* Open error logging file, if not already open, and write vtable
90   verification failure messages (LOG_MSG) to the log file.  Also
91   generate a backtrace in the log file, if GENERATE_BACKTRACE is
92   set.  */
93
94static void
95log_error_message (const char *log_msg, bool generate_backtrace)
96{
97  if (vtv_failures_log_fd == -1)
98    vtv_failures_log_fd = vtv_open_log ("vtable_verification_failures.log");
99
100  if (vtv_failures_log_fd == -1)
101    return;
102
103  vtv_add_to_log (vtv_failures_log_fd, "%s", log_msg);
104
105  if (generate_backtrace)
106    {
107#define STACK_DEPTH 20
108      void *callers[STACK_DEPTH];
109#if !defined (__CYGWIN__) && !defined (__MINGW32__)
110      int actual_depth = backtrace (callers, STACK_DEPTH);
111      backtrace_symbols_fd (callers, actual_depth, vtv_failures_log_fd);
112#endif
113    }
114}
115
116/* In the case where a vtable map variable is the only instance of the
117   variable we have seen, it points directly to the set of valid
118   vtable pointers.  All subsequent instances of the 'same' vtable map
119   variable point to the first vtable map variable.  This function,
120   given a vtable map variable PTR, checks a bit to see whether it's
121   pointing directly to the data set or to the first vtable map
122   variable.  */
123
124static inline bool
125is_set_handle_handle (void * ptr)
126{
127  return ((unsigned long) ptr & SET_HANDLE_HANDLE_BIT)
128                                                      == SET_HANDLE_HANDLE_BIT;
129}
130
131/* Returns the actual pointer value of a vtable map variable, PTR (see
132   comments for is_set_handle_handle for more details).  */
133
134static inline vtv_set_handle *
135ptr_from_set_handle_handle (void * ptr)
136{
137  return (vtv_set_handle *) ((unsigned long) ptr & ~SET_HANDLE_HANDLE_BIT);
138}
139
140/* Given a vtable map variable, PTR, this function sets the bit that
141   says this is the second (or later) instance of a vtable map
142   variable.  */
143
144static inline vtv_set_handle_handle
145set_handle_handle (vtv_set_handle * ptr)
146{
147  return (vtv_set_handle_handle) ((unsigned long) ptr | SET_HANDLE_HANDLE_BIT);
148}
149
150/* This function is called from __VLTVerifyVtablePointerDebug; it
151   sends as much debugging information as it can to the error log
152   file, then calls __vtv_verify_fail.  SET_HANDLE_PTR is the pointer
153   to the set of valid vtable pointers, VTBL_PTR is the pointer that
154   was not found in the set, and DEBUG_MSG is the message to be
155   written to the log file before failing. n */
156
157void
158__vtv_verify_fail_debug (void **set_handle_ptr, const void *vtbl_ptr,
159                         const char *debug_msg)
160{
161  log_error_message (debug_msg, false);
162
163  /* Call the public interface in case it has been overwritten by
164     user.  */
165  __vtv_verify_fail (set_handle_ptr, vtbl_ptr);
166
167  log_error_message ("Returned from __vtv_verify_fail."
168                     " Secondary verification succeeded.\n", false);
169}
170
171/* This function calls __fortify_fail with a FAILURE_MSG and then
172   calls abort.  */
173
174void
175__vtv_really_fail (const char *failure_msg)
176{
177  __fortify_fail (failure_msg);
178
179  /* We should never get this far; __fortify_fail calls __libc_message
180     which prints out a back trace and a memory dump and then is
181     supposed to call abort, but let's play it safe anyway and call abort
182     ourselves.  */
183  abort ();
184}
185
186/* This function takes an error MSG, a vtable map variable
187   (DATA_SET_PTR) and a vtable pointer (VTBL_PTR).  It is called when
188   an attempt to verify VTBL_PTR with the set pointed to by
189   DATA_SET_PTR failed.  It outputs a failure message with the
190   addresses involved, and calls __vtv_really_fail.  */
191
192static void
193vtv_fail (const char *msg, void **data_set_ptr, const void *vtbl_ptr)
194{
195  char buffer[128];
196  int buf_len;
197  const char *format_str =
198                 "*** Unable to verify vtable pointer (%p) in set (%p) *** \n";
199
200  snprintf (buffer, sizeof (buffer), format_str, vtbl_ptr,
201            is_set_handle_handle(*data_set_ptr) ?
202              ptr_from_set_handle_handle (*data_set_ptr) :
203	      *data_set_ptr);
204  buf_len = strlen (buffer);
205  /*  Send this to to stderr.  */
206  write (2, buffer, buf_len);
207
208  if (!vtv_no_abort)
209    __vtv_really_fail (msg);
210}
211
212/* Send information about what we were trying to do when verification
213   failed to the error log, then call vtv_fail.  This function can be
214   overwritten/replaced by the user, to implement a secondary
215   verification function instead.  DATA_SET_PTR is the vtable map
216   variable used for the failed verification, and VTBL_PTR is the
217   vtable pointer that was not found in the set.  */
218
219void
220__vtv_verify_fail (void **data_set_ptr, const void *vtbl_ptr)
221{
222  char log_msg[256];
223  snprintf (log_msg, sizeof (log_msg), "Looking for vtable %p in set %p.\n",
224            vtbl_ptr,
225            is_set_handle_handle (*data_set_ptr) ?
226              ptr_from_set_handle_handle (*data_set_ptr) :
227              *data_set_ptr);
228  log_error_message (log_msg, false);
229
230  const char *format_str =
231            "*** Unable to verify vtable pointer (%p) in set (%p) *** \n";
232  snprintf (log_msg, sizeof (log_msg), format_str, vtbl_ptr, *data_set_ptr);
233  log_error_message (log_msg, false);
234  log_error_message ("  Backtrace: \n", true);
235
236  const char *fail_msg = "Potential vtable pointer corruption detected!!\n";
237  vtv_fail (fail_msg, data_set_ptr, vtbl_ptr);
238}
239
240