1 #include <linux/interrupt.h>
2 #include <linux/kdebug.h>
3 #include <linux/kmemcheck.h>
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/ptrace.h>
7 #include <linux/stacktrace.h>
8 #include <linux/string.h>
13 enum kmemcheck_error_type
{
14 KMEMCHECK_ERROR_INVALID_ACCESS
,
18 #define SHADOW_COPY_SIZE (1 << CONFIG_KMEMCHECK_SHADOW_COPY_SHIFT)
20 struct kmemcheck_error
{
21 enum kmemcheck_error_type type
;
24 /* KMEMCHECK_ERROR_INVALID_ACCESS */
26 /* Kind of access that caused the error */
27 enum kmemcheck_shadow state
;
28 /* Address and size of the erroneous read */
29 unsigned long address
;
35 struct stack_trace trace
;
36 unsigned long trace_entries
[32];
38 /* We compress it to a char. */
39 unsigned char shadow_copy
[SHADOW_COPY_SIZE
];
40 unsigned char memory_copy
[SHADOW_COPY_SIZE
];
44 * Create a ring queue of errors to output. We can't call printk() directly
45 * from the kmemcheck traps, since this may call the console drivers and
46 * result in a recursive fault.
48 static struct kmemcheck_error error_fifo
[CONFIG_KMEMCHECK_QUEUE_SIZE
];
49 static unsigned int error_count
;
50 static unsigned int error_rd
;
51 static unsigned int error_wr
;
52 static unsigned int error_missed_count
;
54 static struct kmemcheck_error
*error_next_wr(void)
56 struct kmemcheck_error
*e
;
58 if (error_count
== ARRAY_SIZE(error_fifo
)) {
63 e
= &error_fifo
[error_wr
];
64 if (++error_wr
== ARRAY_SIZE(error_fifo
))
70 static struct kmemcheck_error
*error_next_rd(void)
72 struct kmemcheck_error
*e
;
77 e
= &error_fifo
[error_rd
];
78 if (++error_rd
== ARRAY_SIZE(error_fifo
))
84 void kmemcheck_error_recall(void)
86 static const char *desc
[] = {
87 [KMEMCHECK_SHADOW_UNALLOCATED
] = "unallocated",
88 [KMEMCHECK_SHADOW_UNINITIALIZED
] = "uninitialized",
89 [KMEMCHECK_SHADOW_INITIALIZED
] = "initialized",
90 [KMEMCHECK_SHADOW_FREED
] = "freed",
93 static const char short_desc
[] = {
94 [KMEMCHECK_SHADOW_UNALLOCATED
] = 'a',
95 [KMEMCHECK_SHADOW_UNINITIALIZED
] = 'u',
96 [KMEMCHECK_SHADOW_INITIALIZED
] = 'i',
97 [KMEMCHECK_SHADOW_FREED
] = 'f',
100 struct kmemcheck_error
*e
;
108 case KMEMCHECK_ERROR_INVALID_ACCESS
:
109 printk(KERN_WARNING
"WARNING: kmemcheck: Caught %d-bit read from %s memory (%p)\n",
110 8 * e
->size
, e
->state
< ARRAY_SIZE(desc
) ?
111 desc
[e
->state
] : "(invalid shadow state)",
112 (void *) e
->address
);
114 printk(KERN_WARNING
);
115 for (i
= 0; i
< SHADOW_COPY_SIZE
; ++i
)
116 printk(KERN_CONT
"%02x", e
->memory_copy
[i
]);
117 printk(KERN_CONT
"\n");
119 printk(KERN_WARNING
);
120 for (i
= 0; i
< SHADOW_COPY_SIZE
; ++i
) {
121 if (e
->shadow_copy
[i
] < ARRAY_SIZE(short_desc
))
122 printk(KERN_CONT
" %c", short_desc
[e
->shadow_copy
[i
]]);
124 printk(KERN_CONT
" ?");
126 printk(KERN_CONT
"\n");
127 printk(KERN_WARNING
"%*c\n", 2 + 2
128 * (int) (e
->address
& (SHADOW_COPY_SIZE
- 1)), '^');
130 case KMEMCHECK_ERROR_BUG
:
131 printk(KERN_EMERG
"ERROR: kmemcheck: Fatal error\n");
135 __show_regs(&e
->regs
, 1);
136 print_stack_trace(&e
->trace
, 0);
139 static void do_wakeup(unsigned long data
)
141 while (error_count
> 0)
142 kmemcheck_error_recall();
144 if (error_missed_count
> 0) {
145 printk(KERN_WARNING
"kmemcheck: Lost %d error reports because "
146 "the queue was too small\n", error_missed_count
);
147 error_missed_count
= 0;
151 static DECLARE_TASKLET(kmemcheck_tasklet
, &do_wakeup
, 0);
154 * Save the context of an error report.
156 void kmemcheck_error_save(enum kmemcheck_shadow state
,
157 unsigned long address
, unsigned int size
, struct pt_regs
*regs
)
159 static unsigned long prev_ip
;
161 struct kmemcheck_error
*e
;
165 /* Don't report several adjacent errors from the same EIP. */
166 if (regs
->ip
== prev_ip
)
174 e
->type
= KMEMCHECK_ERROR_INVALID_ACCESS
;
177 e
->address
= address
;
181 memcpy(&e
->regs
, regs
, sizeof(*regs
));
183 /* Save stack trace */
184 e
->trace
.nr_entries
= 0;
185 e
->trace
.entries
= e
->trace_entries
;
186 e
->trace
.max_entries
= ARRAY_SIZE(e
->trace_entries
);
188 save_stack_trace_regs(regs
, &e
->trace
);
190 /* Round address down to nearest 16 bytes */
191 shadow_copy
= kmemcheck_shadow_lookup(address
192 & ~(SHADOW_COPY_SIZE
- 1));
193 BUG_ON(!shadow_copy
);
195 memcpy(e
->shadow_copy
, shadow_copy
, SHADOW_COPY_SIZE
);
197 kmemcheck_show_addr(address
);
198 memory_copy
= (void *) (address
& ~(SHADOW_COPY_SIZE
- 1));
199 memcpy(e
->memory_copy
, memory_copy
, SHADOW_COPY_SIZE
);
200 kmemcheck_hide_addr(address
);
202 tasklet_hi_schedule_first(&kmemcheck_tasklet
);
206 * Save the context of a kmemcheck bug.
208 void kmemcheck_error_save_bug(struct pt_regs
*regs
)
210 struct kmemcheck_error
*e
;
216 e
->type
= KMEMCHECK_ERROR_BUG
;
218 memcpy(&e
->regs
, regs
, sizeof(*regs
));
220 e
->trace
.nr_entries
= 0;
221 e
->trace
.entries
= e
->trace_entries
;
222 e
->trace
.max_entries
= ARRAY_SIZE(e
->trace_entries
);
224 save_stack_trace(&e
->trace
);
226 tasklet_hi_schedule_first(&kmemcheck_tasklet
);