@@ -1272,7 +1272,7 @@ static void kill_me_maybe(struct callback_head *cb)
12721272 flags |= MF_MUST_KILL ;
12731273
12741274 ret = memory_failure (p -> mce_addr >> PAGE_SHIFT , flags );
1275- if (!ret && !( p -> mce_kflags & MCE_IN_KERNEL_COPYIN ) ) {
1275+ if (!ret ) {
12761276 set_mce_nospec (p -> mce_addr >> PAGE_SHIFT , p -> mce_whole_page );
12771277 sync_core ();
12781278 return ;
@@ -1286,15 +1286,21 @@ static void kill_me_maybe(struct callback_head *cb)
12861286 if (ret == - EHWPOISON )
12871287 return ;
12881288
1289- if (p -> mce_vaddr != (void __user * )-1l ) {
1290- force_sig_mceerr (BUS_MCEERR_AR , p -> mce_vaddr , PAGE_SHIFT );
1291- } else {
1292- pr_err ("Memory error not recovered" );
1293- kill_me_now (cb );
1294- }
1289+ pr_err ("Memory error not recovered" );
1290+ kill_me_now (cb );
1291+ }
1292+
1293+ static void kill_me_never (struct callback_head * cb )
1294+ {
1295+ struct task_struct * p = container_of (cb , struct task_struct , mce_kill_me );
1296+
1297+ p -> mce_count = 0 ;
1298+ pr_err ("Kernel accessed poison in user space at %llx\n" , p -> mce_addr );
1299+ if (!memory_failure (p -> mce_addr >> PAGE_SHIFT , 0 ))
1300+ set_mce_nospec (p -> mce_addr >> PAGE_SHIFT , p -> mce_whole_page );
12951301}
12961302
1297- static void queue_task_work (struct mce * m , char * msg , int kill_current_task )
1303+ static void queue_task_work (struct mce * m , char * msg , void ( * func )( struct callback_head * ) )
12981304{
12991305 int count = ++ current -> mce_count ;
13001306
@@ -1304,11 +1310,7 @@ static void queue_task_work(struct mce *m, char *msg, int kill_current_task)
13041310 current -> mce_kflags = m -> kflags ;
13051311 current -> mce_ripv = !!(m -> mcgstatus & MCG_STATUS_RIPV );
13061312 current -> mce_whole_page = whole_page (m );
1307-
1308- if (kill_current_task )
1309- current -> mce_kill_me .func = kill_me_now ;
1310- else
1311- current -> mce_kill_me .func = kill_me_maybe ;
1313+ current -> mce_kill_me .func = func ;
13121314 }
13131315
13141316 /* Ten is likely overkill. Don't expect more than two faults before task_work() */
@@ -1459,7 +1461,10 @@ noinstr void do_machine_check(struct pt_regs *regs)
14591461 /* If this triggers there is no way to recover. Die hard. */
14601462 BUG_ON (!on_thread_stack () || !user_mode (regs ));
14611463
1462- queue_task_work (& m , msg , kill_current_task );
1464+ if (kill_current_task )
1465+ queue_task_work (& m , msg , kill_me_now );
1466+ else
1467+ queue_task_work (& m , msg , kill_me_maybe );
14631468
14641469 } else {
14651470 /*
@@ -1477,7 +1482,7 @@ noinstr void do_machine_check(struct pt_regs *regs)
14771482 }
14781483
14791484 if (m .kflags & MCE_IN_KERNEL_COPYIN )
1480- queue_task_work (& m , msg , kill_current_task );
1485+ queue_task_work (& m , msg , kill_me_never );
14811486 }
14821487out :
14831488 mce_wrmsrl (MSR_IA32_MCG_STATUS , 0 );
0 commit comments