Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-linus-2020-01-03' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux

Pull thread fixes from Christian Brauner:
"Here are two fixes:

- Panic earlier when global init exits to generate useable coredumps.

Currently, when global init and all threads in its thread-group
have exited we panic via:

do_exit()
-> exit_notify()
-> forget_original_parent()
-> find_child_reaper()

This makes it hard to extract a useable coredump for global init
from a kernel crashdump because by the time we panic exit_mm() will
have already released global init's mm. We now panic slightly
earlier. This has been a problem in certain environments such as
Android.

- Fix a race in assigning and reading taskstats for thread-groups
with more than one thread.

This patch has been waiting for quite a while since people
disagreed on what the correct fix was at first"

* tag 'for-linus-2020-01-03' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux:
exit: panic before exit_mm() on global init exit
taskstats: fix data-race

+27 -15
+8 -4
kernel/exit.c
··· 517 517 } 518 518 519 519 write_unlock_irq(&tasklist_lock); 520 - if (unlikely(pid_ns == &init_pid_ns)) { 521 - panic("Attempted to kill init! exitcode=0x%08x\n", 522 - father->signal->group_exit_code ?: father->exit_code); 523 - } 524 520 525 521 list_for_each_entry_safe(p, n, dead, ptrace_entry) { 526 522 list_del_init(&p->ptrace_entry); ··· 762 766 acct_update_integrals(tsk); 763 767 group_dead = atomic_dec_and_test(&tsk->signal->live); 764 768 if (group_dead) { 769 + /* 770 + * If the last thread of global init has exited, panic 771 + * immediately to get a useable coredump. 772 + */ 773 + if (unlikely(is_global_init(tsk))) 774 + panic("Attempted to kill init! exitcode=0x%08x\n", 775 + tsk->signal->group_exit_code ?: (int)code); 776 + 765 777 #ifdef CONFIG_POSIX_TIMERS 766 778 hrtimer_cancel(&tsk->signal->real_timer); 767 779 exit_itimers(tsk->signal);
+19 -11
kernel/taskstats.c
··· 554 554 static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk) 555 555 { 556 556 struct signal_struct *sig = tsk->signal; 557 - struct taskstats *stats; 557 + struct taskstats *stats_new, *stats; 558 558 559 - if (sig->stats || thread_group_empty(tsk)) 560 - goto ret; 559 + /* Pairs with smp_store_release() below. */ 560 + stats = smp_load_acquire(&sig->stats); 561 + if (stats || thread_group_empty(tsk)) 562 + return stats; 561 563 562 564 /* No problem if kmem_cache_zalloc() fails */ 563 - stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); 565 + stats_new = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); 564 566 565 567 spin_lock_irq(&tsk->sighand->siglock); 566 - if (!sig->stats) { 567 - sig->stats = stats; 568 - stats = NULL; 568 + stats = sig->stats; 569 + if (!stats) { 570 + /* 571 + * Pairs with smp_store_release() above and order the 572 + * kmem_cache_zalloc(). 573 + */ 574 + smp_store_release(&sig->stats, stats_new); 575 + stats = stats_new; 576 + stats_new = NULL; 569 577 } 570 578 spin_unlock_irq(&tsk->sighand->siglock); 571 579 572 - if (stats) 573 - kmem_cache_free(taskstats_cache, stats); 574 - ret: 575 - return sig->stats; 580 + if (stats_new) 581 + kmem_cache_free(taskstats_cache, stats_new); 582 + 583 + return stats; 576 584 } 577 585 578 586 /* Send pid data out on exit */