Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cfi.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, 2013 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #ifndef __CFI_H__
20 #define __CFI_H__
21 
22 #include <glib.h>
23 #include "common.h"
24 #include "target_api.h"
25 #include "probe_api.h"
26 
27 /*
28  * Our CFI implementation handles multithreaded targets, and provides a
29  * few configuration options.
30  *
31  * Right now, it only supports dynamic CFI, seeded from a root set of target
32  * functions. When we start dynamic CFI, we disasm the root set
33  * functions, and place probes on any of their control flow transfer
34  * instructions (well, right now, just CALL/RET). If the CFI_AUTOFOLLOW
35  * flag is set, when control is transferred to a currently untracked
36  * part of the code, we attempt to probe that code as well (growing our
37  * tracked function set).
38  *
39  * See more below about static CFI for how it *would* work, and why it
40  * is basically inferior to dynamic CFI -- and thus why we will never
41  * implement it :).
42  */
43 
44 typedef enum {
45  /*
46  * In dynamic mode, we place probes on control transfer instructions
47  * (initially only CALL and RET) within each tracked function. When
48  * a CALL probe is hit, a posthandler probe records the return addr
49  * on our shadow stack; when a RET probe is hit, a prehandler probe
50  * pop/checks the return addr with our shadow stack.
51  *
52  * Dynamic mode is well-suited to the case when when you have
53  * control flow instructions that are runtime-dependent (i.e., are
54  * not just absolute calls or jumps); most programs have these. It
55  * also frees you from having to insert
56  */
58  /*
59  * NB: right now, static mode is unsupported, since its utility is
60  * highly debatable. The biggest reason not to do is because it
61  * basically requires more probes per function. Consider: if we
62  * have to maintain our shadow stack via the entry/exit probes, BUT
63  * also have to implement AUTOFOLLOW by placing probes on any
64  * indirect control flow transfer functions inside the function --
65  * we may as well do a dynamic analysis and record return addresses
66  * *at* the control flow transfer sites themselves; this is much cheaper.
67  *
68  * In static mode, we place probes on each tracked function's first
69  * instruction, and on any return instructions, and push the retaddr
70  * onto our shadow stack when we hit the first instr, and pop/check
71  * we leave the function. Then if AUTOFOLLOW support is requested,
72  * we also have to probe inside the function to catch control flow
73  * transfers.
74  */
76 } cfi_mode_t;
77 
78 typedef enum {
79  CFI_NONE = 0,
80  /*
81  * AUTOFOLLOW means that for each tracked function, its internal
82  * control flow instructions are probed as well, and when they are
83  * hit, we add more probes to their target functions (or code
84  * blocks; might not be a function). If we can't figure out what
85  * the code block is, we would have to single step to maintain
86  * control; we don't do that yet (and that behavior will be
87  * controlled by CFI_SINGLESTEP_UNKNOWN below).
88  *
89  * This happens automatically; this flag disables it.
90  */
91  CFI_NOAUTOFOLLOW = 1 << 0,
92  /*
93  * If control flow becomes unknown, single step until we reach a
94  * region that is no longer unknown, and track all control flow
95  * until we return to a known location.
96  */
98  /*
99  * If a violation is detected, try to fix up the return address on
100  * the stack before returning! This might not end up working
101  * semantically within the target, but it's easy to expose :).
102  */
103  CFI_FIXUP = 1 << 2,
104 } cfi_flags_t;
105 
106 struct cfi_status;
107 struct cfi_thread_status;
108 struct cfi_data;
109 
110 /*
111  * Create a CFI "probe", starting from a set of root functions.
112  *
113  * NB: if flags & CFI_AUTOFOLLOW, you had better only have a single CFI
114  * "probe" on this target/tid pair. If you try to add another, they
115  * will interfere with each other by trying to disasm each others' code
116  * blocks as they add new tracked functions, and if one probe has
117  * already probed a block that another probe then tries to disassemble,
118  * the disassembly will fail if software probes are in place!!
119  */
120 struct probe *probe_cfi(struct target *target,tid_t tid,
121  cfi_mode_t mode,cfi_flags_t flags,
122  struct array_list *root_functions,
123  struct array_list *root_addrs,
125  void *handler_data);
126 
127 char *cfi_thread_backtrace(struct cfi_data *cfi,struct cfi_thread_status *cts,
128  char *sep);
129 
130 struct cfi_status {
131  uint8_t isviolation:1;
132 
135 
136  uint16_t violations;
138 };
139 
144 };
145 
146 struct cfi_data {
149 
150  struct target *target;
151 
152  /*
153  * A specific tid to track.
154  */
155  int tid;
156 
157  /*
158  * A hashtable of disassembled functions. We need to cache them to
159  * make sure we don't try to disasm them after we have started
160  * probing them!
161  */
162  GHashTable *disfuncs;
163 
164  /*
165  * A hashtable of disassembled functions THAT DO NOT have any
166  * control flow exiting from them, as far as we can tell. We need
167  * to cache them to make sure we don't try to disasm them after we
168  * have started probing them!
169  *
170  * AND, we cannot add calls/jumps to them into our stack! We must
171  * push NULL instead.
172  */
173  GHashTable *disfuncs_noflow;
174 
175  /*
176  * The internal probes we use.
177  */
178  GHashTable *probes;
179 
180  /*
181  * Since we support multithreaded targets, we have to keep a shadow
182  * stack for each thread.
183  */
184  GHashTable *thread_status;
185 
186  /*
187  * This table tracks which return probes are probes on RET
188  * instructions that have immediates. We want to handle these
189  * differently than normal RETs, because these pop the retaddr
190  * first, then release stack bytes. This pattern, I believe, is
191  * only useful when returning to a different procedure and reusing
192  * the current procedure's stack frame. So, we have to detect this
193  * as a valid RET, even though it's munging the stack.
194  */
195  GHashTable *ret_immediate_addrs;
196 
197  /* The high-level probe. */
198  struct probe *cfi_probe;
199 
200  /* Overall status of the high-level probe. */
202 };
203 
204 #endif /* __CFI_H__ */
struct target * target
Definition: cfi.h:150
struct probe * probe_cfi(struct target *target, tid_t tid, cfi_mode_t mode, cfi_flags_t flags, struct array_list *root_functions, struct array_list *root_addrs, probe_handler_t pre_handler, probe_handler_t post_handler, void *handler_data)
Definition: cfi_util.c:1118
result_t pre_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: spf.c:903
struct array_list * shadow_stack_symbols
Definition: cfi.h:142
struct cfi_status status
Definition: cfi.h:201
int nonrootsethits
Definition: cfi.h:137
int32_t tid_t
Definition: common.h:36
GHashTable * thread_status
Definition: cfi.h:184
cfi_mode_t mode
Definition: cfi.h:147
cfi_flags_t flags
Definition: cfi.h:148
Definition: cfi.h:79
char * cfi_thread_backtrace(struct cfi_data *cfi, struct cfi_thread_status *cts, char *sep)
Definition: cfi_util.c:1056
ADDR oldretaddr
Definition: cfi.h:133
result_t(* probe_handler_t)(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
Definition: probe_api.h:70
struct array_list * shadow_stack
Definition: cfi.h:141
struct cfi_status status
Definition: cfi.h:143
GHashTable * probes
Definition: cfi.h:178
tid_t tid
Definition: probe.h:344
int tid
Definition: cfi.h:155
Definition: cfi.h:75
cfi_flags_t
Definition: cfi.h:78
Definition: probe.h:308
GHashTable * ret_immediate_addrs
Definition: cfi.h:195
result_t post_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: spf.c:908
cfi_mode_t
Definition: cfi.h:44
GHashTable * disfuncs
Definition: cfi.h:162
uint32_t ADDR
Definition: common.h:64
uint16_t violations
Definition: cfi.h:136
Definition: cfi.h:146
uint8_t isviolation
Definition: cfi.h:131
ADDR newretaddr
Definition: cfi.h:134
GHashTable * disfuncs_noflow
Definition: cfi.h:173
struct probe * cfi_probe
Definition: cfi.h:198
Definition: cfi.h:103