• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * UBSAN error reporting functions
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
5  * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  */
12 
13 #include <linux/bitops.h>
14 #include <linux/bug.h>
15 #include <linux/ctype.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/sched.h>
20 
21 #include "ubsan.h"
22 
23 const char *type_check_kinds[] = {
24 	"load of",
25 	"store to",
26 	"reference binding to",
27 	"member access within",
28 	"member call on",
29 	"constructor call on",
30 	"downcast of",
31 	"downcast of"
32 };
33 
34 #define REPORTED_BIT 31
35 
36 #if (BITS_PER_LONG == 64) && defined(__BIG_ENDIAN)
37 #define COLUMN_MASK (~(1U << REPORTED_BIT))
38 #define LINE_MASK   (~0U)
39 #else
40 #define COLUMN_MASK   (~0U)
41 #define LINE_MASK (~(1U << REPORTED_BIT))
42 #endif
43 
44 #define VALUE_LENGTH 40
45 
was_reported(struct source_location * location)46 static bool was_reported(struct source_location *location)
47 {
48 	return test_and_set_bit(REPORTED_BIT, &location->reported);
49 }
50 
print_source_location(const char * prefix,struct source_location * loc)51 static void print_source_location(const char *prefix,
52 				struct source_location *loc)
53 {
54 	pr_err("%s %s:%d:%d\n", prefix, loc->file_name,
55 		loc->line & LINE_MASK, loc->column & COLUMN_MASK);
56 }
57 
suppress_report(struct source_location * loc)58 static bool suppress_report(struct source_location *loc)
59 {
60 	return current->in_ubsan || was_reported(loc);
61 }
62 
type_is_int(struct type_descriptor * type)63 static bool type_is_int(struct type_descriptor *type)
64 {
65 	return type->type_kind == type_kind_int;
66 }
67 
type_is_signed(struct type_descriptor * type)68 static bool type_is_signed(struct type_descriptor *type)
69 {
70 	WARN_ON(!type_is_int(type));
71 	return  type->type_info & 1;
72 }
73 
type_bit_width(struct type_descriptor * type)74 static unsigned type_bit_width(struct type_descriptor *type)
75 {
76 	return 1 << (type->type_info >> 1);
77 }
78 
is_inline_int(struct type_descriptor * type)79 static bool is_inline_int(struct type_descriptor *type)
80 {
81 	unsigned inline_bits = sizeof(unsigned long)*8;
82 	unsigned bits = type_bit_width(type);
83 
84 	WARN_ON(!type_is_int(type));
85 
86 	return bits <= inline_bits;
87 }
88 
get_signed_val(struct type_descriptor * type,void * val)89 static s_max get_signed_val(struct type_descriptor *type, void *val)
90 {
91 	if (is_inline_int(type)) {
92 		unsigned extra_bits = sizeof(s_max)*8 - type_bit_width(type);
93 		unsigned long ulong_val = (unsigned long)val;
94 
95 		return ((s_max)ulong_val) << extra_bits >> extra_bits;
96 	}
97 
98 	if (type_bit_width(type) == 64)
99 		return *(s64 *)val;
100 
101 	return *(s_max *)val;
102 }
103 
val_is_negative(struct type_descriptor * type,void * val)104 static bool val_is_negative(struct type_descriptor *type, void *val)
105 {
106 	return type_is_signed(type) && get_signed_val(type, val) < 0;
107 }
108 
get_unsigned_val(struct type_descriptor * type,void * val)109 static u_max get_unsigned_val(struct type_descriptor *type, void *val)
110 {
111 	if (is_inline_int(type))
112 		return (unsigned long)val;
113 
114 	if (type_bit_width(type) == 64)
115 		return *(u64 *)val;
116 
117 	return *(u_max *)val;
118 }
119 
val_to_string(char * str,size_t size,struct type_descriptor * type,void * value)120 static void val_to_string(char *str, size_t size, struct type_descriptor *type,
121 			void *value)
122 {
123 	if (type_is_int(type)) {
124 		if (type_bit_width(type) == 128) {
125 #if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
126 			u_max val = get_unsigned_val(type, value);
127 
128 			scnprintf(str, size, "0x%08x%08x%08x%08x",
129 				(u32)(val >> 96),
130 				(u32)(val >> 64),
131 				(u32)(val >> 32),
132 				(u32)(val));
133 #else
134 			WARN_ON(1);
135 #endif
136 		} else if (type_is_signed(type)) {
137 			scnprintf(str, size, "%lld",
138 				(s64)get_signed_val(type, value));
139 		} else {
140 			scnprintf(str, size, "%llu",
141 				(u64)get_unsigned_val(type, value));
142 		}
143 	}
144 }
145 
146 static DEFINE_SPINLOCK(report_lock);
147 
ubsan_prologue(struct source_location * location,unsigned long * flags)148 static void ubsan_prologue(struct source_location *location,
149 			unsigned long *flags)
150 {
151 	current->in_ubsan++;
152 	spin_lock_irqsave(&report_lock, *flags);
153 
154 	pr_err("========================================"
155 		"========================================\n");
156 	print_source_location("UBSAN: Undefined behaviour in", location);
157 }
158 
ubsan_epilogue(unsigned long * flags)159 static void ubsan_epilogue(unsigned long *flags)
160 {
161 	dump_stack();
162 	pr_err("========================================"
163 		"========================================\n");
164 	spin_unlock_irqrestore(&report_lock, *flags);
165 	current->in_ubsan--;
166 }
167 
handle_overflow(struct overflow_data * data,void * lhs,void * rhs,char op)168 static void handle_overflow(struct overflow_data *data, void *lhs,
169 			void *rhs, char op)
170 {
171 
172 	struct type_descriptor *type = data->type;
173 	unsigned long flags;
174 	char lhs_val_str[VALUE_LENGTH];
175 	char rhs_val_str[VALUE_LENGTH];
176 
177 	if (suppress_report(&data->location))
178 		return;
179 
180 	ubsan_prologue(&data->location, &flags);
181 
182 	val_to_string(lhs_val_str, sizeof(lhs_val_str), type, lhs);
183 	val_to_string(rhs_val_str, sizeof(rhs_val_str), type, rhs);
184 	pr_err("%s integer overflow:\n",
185 		type_is_signed(type) ? "signed" : "unsigned");
186 	pr_err("%s %c %s cannot be represented in type %s\n",
187 		lhs_val_str,
188 		op,
189 		rhs_val_str,
190 		type->type_name);
191 
192 	ubsan_epilogue(&flags);
193 }
194 
__ubsan_handle_add_overflow(struct overflow_data * data,void * lhs,void * rhs)195 void __ubsan_handle_add_overflow(struct overflow_data *data,
196 				void *lhs, void *rhs)
197 {
198 
199 	handle_overflow(data, lhs, rhs, '+');
200 }
201 EXPORT_SYMBOL(__ubsan_handle_add_overflow);
202 
__ubsan_handle_sub_overflow(struct overflow_data * data,void * lhs,void * rhs)203 void __ubsan_handle_sub_overflow(struct overflow_data *data,
204 				void *lhs, void *rhs)
205 {
206 	handle_overflow(data, lhs, rhs, '-');
207 }
208 EXPORT_SYMBOL(__ubsan_handle_sub_overflow);
209 
__ubsan_handle_mul_overflow(struct overflow_data * data,void * lhs,void * rhs)210 void __ubsan_handle_mul_overflow(struct overflow_data *data,
211 				void *lhs, void *rhs)
212 {
213 	handle_overflow(data, lhs, rhs, '*');
214 }
215 EXPORT_SYMBOL(__ubsan_handle_mul_overflow);
216 
__ubsan_handle_negate_overflow(struct overflow_data * data,void * old_val)217 void __ubsan_handle_negate_overflow(struct overflow_data *data,
218 				void *old_val)
219 {
220 	unsigned long flags;
221 	char old_val_str[VALUE_LENGTH];
222 
223 	if (suppress_report(&data->location))
224 		return;
225 
226 	ubsan_prologue(&data->location, &flags);
227 
228 	val_to_string(old_val_str, sizeof(old_val_str), data->type, old_val);
229 
230 	pr_err("negation of %s cannot be represented in type %s:\n",
231 		old_val_str, data->type->type_name);
232 
233 	ubsan_epilogue(&flags);
234 }
235 EXPORT_SYMBOL(__ubsan_handle_negate_overflow);
236 
237 
__ubsan_handle_divrem_overflow(struct overflow_data * data,void * lhs,void * rhs)238 void __ubsan_handle_divrem_overflow(struct overflow_data *data,
239 				void *lhs, void *rhs)
240 {
241 	unsigned long flags;
242 	char rhs_val_str[VALUE_LENGTH];
243 
244 	if (suppress_report(&data->location))
245 		return;
246 
247 	ubsan_prologue(&data->location, &flags);
248 
249 	val_to_string(rhs_val_str, sizeof(rhs_val_str), data->type, rhs);
250 
251 	if (type_is_signed(data->type) && get_signed_val(data->type, rhs) == -1)
252 		pr_err("division of %s by -1 cannot be represented in type %s\n",
253 			rhs_val_str, data->type->type_name);
254 	else
255 		pr_err("division by zero\n");
256 
257 	ubsan_epilogue(&flags);
258 }
259 EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
260 
handle_null_ptr_deref(struct type_mismatch_data_common * data)261 static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
262 {
263 	unsigned long flags;
264 
265 	if (suppress_report(data->location))
266 		return;
267 
268 	ubsan_prologue(data->location, &flags);
269 
270 	pr_err("%s null pointer of type %s\n",
271 		type_check_kinds[data->type_check_kind],
272 		data->type->type_name);
273 
274 	ubsan_epilogue(&flags);
275 }
276 
handle_misaligned_access(struct type_mismatch_data_common * data,unsigned long ptr)277 static void handle_misaligned_access(struct type_mismatch_data_common *data,
278 				unsigned long ptr)
279 {
280 	unsigned long flags;
281 
282 	if (suppress_report(data->location))
283 		return;
284 
285 	ubsan_prologue(data->location, &flags);
286 
287 	pr_err("%s misaligned address %p for type %s\n",
288 		type_check_kinds[data->type_check_kind],
289 		(void *)ptr, data->type->type_name);
290 	pr_err("which requires %ld byte alignment\n", data->alignment);
291 
292 	ubsan_epilogue(&flags);
293 }
294 
handle_object_size_mismatch(struct type_mismatch_data_common * data,unsigned long ptr)295 static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
296 					unsigned long ptr)
297 {
298 	unsigned long flags;
299 
300 	if (suppress_report(data->location))
301 		return;
302 
303 	ubsan_prologue(data->location, &flags);
304 	pr_err("%s address %p with insufficient space\n",
305 		type_check_kinds[data->type_check_kind],
306 		(void *) ptr);
307 	pr_err("for an object of type %s\n", data->type->type_name);
308 	ubsan_epilogue(&flags);
309 }
310 
ubsan_type_mismatch_common(struct type_mismatch_data_common * data,unsigned long ptr)311 static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
312 				unsigned long ptr)
313 {
314 
315 	if (!ptr)
316 		handle_null_ptr_deref(data);
317 	else if (data->alignment && !IS_ALIGNED(ptr, data->alignment))
318 		handle_misaligned_access(data, ptr);
319 	else
320 		handle_object_size_mismatch(data, ptr);
321 }
322 
__ubsan_handle_type_mismatch(struct type_mismatch_data * data,void * ptr)323 void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
324 				void *ptr)
325 {
326 	struct type_mismatch_data_common common_data = {
327 		.location = &data->location,
328 		.type = data->type,
329 		.alignment = data->alignment,
330 		.type_check_kind = data->type_check_kind
331 	};
332 
333 	ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
334 }
335 EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
336 
__ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 * data,void * ptr)337 void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
338 				void *ptr)
339 {
340 
341 	struct type_mismatch_data_common common_data = {
342 		.location = &data->location,
343 		.type = data->type,
344 		.alignment = 1UL << data->log_alignment,
345 		.type_check_kind = data->type_check_kind
346 	};
347 
348 	ubsan_type_mismatch_common(&common_data, (unsigned long)ptr);
349 }
350 EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
351 
__ubsan_handle_vla_bound_not_positive(struct vla_bound_data * data,void * bound)352 void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
353 					void *bound)
354 {
355 	unsigned long flags;
356 	char bound_str[VALUE_LENGTH];
357 
358 	if (suppress_report(&data->location))
359 		return;
360 
361 	ubsan_prologue(&data->location, &flags);
362 
363 	val_to_string(bound_str, sizeof(bound_str), data->type, bound);
364 	pr_err("variable length array bound value %s <= 0\n", bound_str);
365 
366 	ubsan_epilogue(&flags);
367 }
368 EXPORT_SYMBOL(__ubsan_handle_vla_bound_not_positive);
369 
__ubsan_handle_out_of_bounds(struct out_of_bounds_data * data,void * index)370 void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, void *index)
371 {
372 	unsigned long flags;
373 	char index_str[VALUE_LENGTH];
374 
375 	if (suppress_report(&data->location))
376 		return;
377 
378 	ubsan_prologue(&data->location, &flags);
379 
380 	val_to_string(index_str, sizeof(index_str), data->index_type, index);
381 	pr_err("index %s is out of range for type %s\n", index_str,
382 		data->array_type->type_name);
383 	ubsan_epilogue(&flags);
384 }
385 EXPORT_SYMBOL(__ubsan_handle_out_of_bounds);
386 
__ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data * data,void * lhs,void * rhs)387 void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
388 					void *lhs, void *rhs)
389 {
390 	unsigned long flags;
391 	struct type_descriptor *rhs_type = data->rhs_type;
392 	struct type_descriptor *lhs_type = data->lhs_type;
393 	char rhs_str[VALUE_LENGTH];
394 	char lhs_str[VALUE_LENGTH];
395 
396 	if (suppress_report(&data->location))
397 		return;
398 
399 	ubsan_prologue(&data->location, &flags);
400 
401 	val_to_string(rhs_str, sizeof(rhs_str), rhs_type, rhs);
402 	val_to_string(lhs_str, sizeof(lhs_str), lhs_type, lhs);
403 
404 	if (val_is_negative(rhs_type, rhs))
405 		pr_err("shift exponent %s is negative\n", rhs_str);
406 
407 	else if (get_unsigned_val(rhs_type, rhs) >=
408 		type_bit_width(lhs_type))
409 		pr_err("shift exponent %s is too large for %u-bit type %s\n",
410 			rhs_str,
411 			type_bit_width(lhs_type),
412 			lhs_type->type_name);
413 	else if (val_is_negative(lhs_type, lhs))
414 		pr_err("left shift of negative value %s\n",
415 			lhs_str);
416 	else
417 		pr_err("left shift of %s by %s places cannot be"
418 			" represented in type %s\n",
419 			lhs_str, rhs_str,
420 			lhs_type->type_name);
421 
422 	ubsan_epilogue(&flags);
423 }
424 EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds);
425 
426 
__ubsan_handle_builtin_unreachable(struct unreachable_data * data)427 void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
428 {
429 	unsigned long flags;
430 
431 	ubsan_prologue(&data->location, &flags);
432 	pr_err("calling __builtin_unreachable()\n");
433 	ubsan_epilogue(&flags);
434 	panic("can't return from __builtin_unreachable()");
435 }
436 EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable);
437 
__ubsan_handle_load_invalid_value(struct invalid_value_data * data,void * val)438 void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
439 				void *val)
440 {
441 	unsigned long flags;
442 	char val_str[VALUE_LENGTH];
443 
444 	if (suppress_report(&data->location))
445 		return;
446 
447 	ubsan_prologue(&data->location, &flags);
448 
449 	val_to_string(val_str, sizeof(val_str), data->type, val);
450 
451 	pr_err("load of value %s is not a valid value for type %s\n",
452 		val_str, data->type->type_name);
453 
454 	ubsan_epilogue(&flags);
455 }
456 EXPORT_SYMBOL(__ubsan_handle_load_invalid_value);
457