diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 42d8c67..f97a7ba 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1140,8 +1140,15 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ goto err_free; err = -ENOMEM; vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_KERNEL); - if (!vc->vc_screenbuf) + if (!vc->vc_screenbuf) { + vc->debug_last_kzalloc = 0; + vc->debug_last_kzalloc_size = 0; + vc->debug_last_ksize = 0; goto err_free; + } + vc->debug_last_kzalloc = (unsigned long) vc->vc_screenbuf; + vc->debug_last_kzalloc_size = vc->vc_screenbuf_size; + vc->debug_last_ksize = ksize(vc->vc_screenbuf); /* If no drivers have overridden us and the user didn't pass a boot option, default to displaying the cursor */ @@ -1193,7 +1200,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned long end; - unsigned int old_rows, old_row_size, first_copied_row; + unsigned int old_cols, old_rows, old_row_size, old_screen_size, first_copied_row; unsigned int new_cols, new_rows, new_row_size, new_screen_size; unsigned int user; unsigned short *newscreen; @@ -1236,7 +1243,9 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, clear_selection(); old_rows = vc->vc_rows; + old_cols = vc->vc_cols; old_row_size = vc->vc_size_row; + old_screen_size = vc->vc_screenbuf_size; err = resize_screen(vc, new_cols, new_rows, user); if (err) { @@ -1285,18 +1294,27 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, while (old_origin < end) { scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth); + if (atomic_read(&kasan_warned)) + goto out; if (rrem) scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem); + if (atomic_read(&kasan_warned)) + goto out; old_origin += old_row_size; new_origin += new_row_size; } if (new_scr_end > new_origin) scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin); + if (atomic_read(&kasan_warned)) + goto out; kfree(vc->vc_screenbuf); vc->vc_screenbuf = newscreen; vc->vc_screenbuf_size = new_screen_size; + vc->debug_last_kzalloc = (unsigned long) newscreen; + vc->debug_last_kzalloc_size = new_screen_size; + vc->debug_last_ksize = ksize(newscreen); set_origin(vc); /* do part of a reset_terminal() */ @@ -1321,6 +1339,10 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num); notify_update(vc); return err; + out: + printk(KERN_INFO "vc->debug_last_kzalloc=%lx vc->debug_last_kzalloc_size=%u vc->debug_last_ksize=%u vc->vc_screenbuf=%lx old_screen_size=%u old_row_size=%u old_rows=%u old_cols=%u new_screen_size=%u new_row_size=%u new_rows=%u new_cols=%u\n", + vc->debug_last_kzalloc, vc->debug_last_kzalloc_size, vc->debug_last_ksize, (unsigned long) vc->vc_screenbuf, old_screen_size, old_row_size, old_rows, old_cols, new_screen_size, new_row_size, new_rows, new_cols); + panic("panic_on_warn set ...\n"); } /** @@ -3401,6 +3423,9 @@ static int __init con_init(void) visual_init(vc, currcons, 1); /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */ vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); + vc->debug_last_kzalloc = (unsigned long) vc->vc_screenbuf; + vc->debug_last_kzalloc_size = vc->vc_screenbuf_size; + vc->debug_last_ksize = ksize(vc->vc_screenbuf); vc_init(vc, vc->vc_rows, vc->vc_cols, currcons || !vc->vc_sw->con_save_screen); } diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 24d4c16..a74e9e6 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -141,6 +141,9 @@ struct vc_data { struct uni_pagedir *vc_uni_pagedir; struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ struct uni_screen *vc_uni_screen; /* unicode screen content */ + unsigned long debug_last_kzalloc; + unsigned int debug_last_kzalloc_size; + unsigned int debug_last_ksize; /* additional information is in vt_kern.h */ }; diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 82d9154..448e511 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -534,6 +534,7 @@ static inline u32 int_sqrt64(u64 x) extern int panic_on_unrecovered_nmi; extern int panic_on_io_nmi; extern int panic_on_warn; +extern atomic_t kasan_warned; extern unsigned long panic_on_taint; extern bool panic_on_taint_nousertaint; extern int sysctl_panic_on_rcu_stall; diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 51ec454..2af9a8d 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -35,6 +35,7 @@ #include "kasan.h" #include "../slab.h" +atomic_t kasan_warned = ATOMIC_INIT(0); /* Shadow layout customization. */ #define SHADOW_BYTES_PER_BLOCK 1 @@ -101,7 +102,7 @@ static void end_report(unsigned long *flags) * panic_mutex in panic(). */ panic_on_warn = 0; - panic("panic_on_warn set ...\n"); + atomic_set(&kasan_warned, 1); } kasan_enable_current(); }