aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAndrey Ryabinin <aryabinin@virtuozzo.com>2018-02-06 18:40:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-06 21:32:46 -0500
commit42440c1f9911b4b7b8ba3dc4e90c1197bc561211 (patch)
treeb89beb05c6a0a42c7e289a8050ba7797aae6a586 /lib
parentb8fe1120b4ba342b4f156d24e952d6e686b20298 (diff)
lib/ubsan: add type mismatch handler for new GCC/Clang
UBSAN=y fails to build with new GCC/clang: arch/x86/kernel/head64.o: In function `sanitize_boot_params': arch/x86/include/asm/bootparam_utils.h:37: undefined reference to `__ubsan_handle_type_mismatch_v1' because Clang and GCC 8 slightly changed ABI for 'type mismatch' errors. Compiler now uses new __ubsan_handle_type_mismatch_v1() function with slightly modified 'struct type_mismatch_data'. Let's add new 'struct type_mismatch_data_common' which is independent from compiler's layout of 'struct type_mismatch_data'. And make __ubsan_handle_type_mismatch[_v1]() functions transform compiler-dependent type mismatch data to our internal representation. This way, we can support both old and new compilers with minimal amount of change. Link: http://lkml.kernel.org/r/20180119152853.16806-1-aryabinin@virtuozzo.com Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Reported-by: Sodagudi Prasad <psodagud@codeaurora.org> Cc: <stable@vger.kernel.org> [4.5+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/ubsan.c48
-rw-r--r--lib/ubsan.h14
2 files changed, 52 insertions, 10 deletions
diff --git a/lib/ubsan.c b/lib/ubsan.c
index 1e2328fa002d..50d1d5c25deb 100644
--- a/lib/ubsan.c
+++ b/lib/ubsan.c
@@ -265,14 +265,14 @@ void __ubsan_handle_divrem_overflow(struct overflow_data *data,
265} 265}
266EXPORT_SYMBOL(__ubsan_handle_divrem_overflow); 266EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
267 267
268static void handle_null_ptr_deref(struct type_mismatch_data *data) 268static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
269{ 269{
270 unsigned long flags; 270 unsigned long flags;
271 271
272 if (suppress_report(&data->location)) 272 if (suppress_report(data->location))
273 return; 273 return;
274 274
275 ubsan_prologue(&data->location, &flags); 275 ubsan_prologue(data->location, &flags);
276 276
277 pr_err("%s null pointer of type %s\n", 277 pr_err("%s null pointer of type %s\n",
278 type_check_kinds[data->type_check_kind], 278 type_check_kinds[data->type_check_kind],
@@ -281,15 +281,15 @@ static void handle_null_ptr_deref(struct type_mismatch_data *data)
281 ubsan_epilogue(&flags); 281 ubsan_epilogue(&flags);
282} 282}
283 283
284static void handle_misaligned_access(struct type_mismatch_data *data, 284static void handle_misaligned_access(struct type_mismatch_data_common *data,
285 unsigned long ptr) 285 unsigned long ptr)
286{ 286{
287 unsigned long flags; 287 unsigned long flags;
288 288
289 if (suppress_report(&data->location)) 289 if (suppress_report(data->location))
290 return; 290 return;
291 291
292 ubsan_prologue(&data->location, &flags); 292 ubsan_prologue(data->location, &flags);
293 293
294 pr_err("%s misaligned address %p for type %s\n", 294 pr_err("%s misaligned address %p for type %s\n",
295 type_check_kinds[data->type_check_kind], 295 type_check_kinds[data->type_check_kind],
@@ -299,15 +299,15 @@ static void handle_misaligned_access(struct type_mismatch_data *data,
299 ubsan_epilogue(&flags); 299 ubsan_epilogue(&flags);
300} 300}
301 301
302static void handle_object_size_mismatch(struct type_mismatch_data *data, 302static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
303 unsigned long ptr) 303 unsigned long ptr)
304{ 304{
305 unsigned long flags; 305 unsigned long flags;
306 306
307 if (suppress_report(&data->location)) 307 if (suppress_report(data->location))
308 return; 308 return;
309 309
310 ubsan_prologue(&data->location, &flags); 310 ubsan_prologue(data->location, &flags);
311 pr_err("%s address %p with insufficient space\n", 311 pr_err("%s address %p with insufficient space\n",
312 type_check_kinds[data->type_check_kind], 312 type_check_kinds[data->type_check_kind],
313 (void *) ptr); 313 (void *) ptr);
@@ -315,7 +315,7 @@ static void handle_object_size_mismatch(struct type_mismatch_data *data,
315 ubsan_epilogue(&flags); 315 ubsan_epilogue(&flags);
316} 316}
317 317
318void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, 318static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
319 unsigned long ptr) 319 unsigned long ptr)
320{ 320{
321 321
@@ -326,8 +326,36 @@ void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
326 else 326 else
327 handle_object_size_mismatch(data, ptr); 327 handle_object_size_mismatch(data, ptr);
328} 328}
329
330void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
331 unsigned long ptr)
332{
333 struct type_mismatch_data_common common_data = {
334 .location = &data->location,
335 .type = data->type,
336 .alignment = data->alignment,
337 .type_check_kind = data->type_check_kind
338 };
339
340 ubsan_type_mismatch_common(&common_data, ptr);
341}
329EXPORT_SYMBOL(__ubsan_handle_type_mismatch); 342EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
330 343
344void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
345 unsigned long ptr)
346{
347
348 struct type_mismatch_data_common common_data = {
349 .location = &data->location,
350 .type = data->type,
351 .alignment = 1UL << data->log_alignment,
352 .type_check_kind = data->type_check_kind
353 };
354
355 ubsan_type_mismatch_common(&common_data, ptr);
356}
357EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
358
331void __ubsan_handle_nonnull_return(struct nonnull_return_data *data) 359void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
332{ 360{
333 unsigned long flags; 361 unsigned long flags;
diff --git a/lib/ubsan.h b/lib/ubsan.h
index 88f23557edbe..7e30b26497e0 100644
--- a/lib/ubsan.h
+++ b/lib/ubsan.h
@@ -37,6 +37,20 @@ struct type_mismatch_data {
37 unsigned char type_check_kind; 37 unsigned char type_check_kind;
38}; 38};
39 39
40struct type_mismatch_data_v1 {
41 struct source_location location;
42 struct type_descriptor *type;
43 unsigned char log_alignment;
44 unsigned char type_check_kind;
45};
46
47struct type_mismatch_data_common {
48 struct source_location *location;
49 struct type_descriptor *type;
50 unsigned long alignment;
51 unsigned char type_check_kind;
52};
53
40struct nonnull_arg_data { 54struct nonnull_arg_data {
41 struct source_location location; 55 struct source_location location;
42 struct source_location attr_location; 56 struct source_location attr_location;