x86/sgx: Do not fail on incomplete sanitization on premature stop of ksgxd
Unsanitized pages trigger WARN_ON() unconditionally, which can panic the whole computer, if /proc/sys/kernel/panic_on_warn is set. In sgx_init(), if misc_register() fails or misc_register() succeeds but neither sgx_drv_init() nor sgx_vepc_init() succeeds, then ksgxd will be prematurely stopped. This may leave unsanitized pages, which will result a false warning. Refine __sgx_sanitize_pages() to return: 1. Zero when the sanitization process is complete or ksgxd has been requested to stop. 2. The number of unsanitized pages otherwise. Fixes: 51ab30eb2ad4 ("x86/sgx: Replace section->init_laundry_list with sgx_dirty_page_list") Reported-by: Paul Menzel <pmenzel@molgen.mpg.de> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-sgx/20220825051827.246698-1-jarkko@kernel.org/T/#u Link: https://lkml.kernel.org/r/20220906000221.34286-2-jarkko@kernel.org
This commit is contained in:
parent
5515d21c68
commit
133e049a3f
@ -49,9 +49,13 @@ static LIST_HEAD(sgx_dirty_page_list);
|
||||
* Reset post-kexec EPC pages to the uninitialized state. The pages are removed
|
||||
* from the input list, and made available for the page allocator. SECS pages
|
||||
* prepending their children in the input list are left intact.
|
||||
*
|
||||
* Return 0 when sanitization was successful or kthread was stopped, and the
|
||||
* number of unsanitized pages otherwise.
|
||||
*/
|
||||
static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
|
||||
static unsigned long __sgx_sanitize_pages(struct list_head *dirty_page_list)
|
||||
{
|
||||
unsigned long left_dirty = 0;
|
||||
struct sgx_epc_page *page;
|
||||
LIST_HEAD(dirty);
|
||||
int ret;
|
||||
@ -59,7 +63,7 @@ static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
|
||||
/* dirty_page_list is thread-local, no need for a lock: */
|
||||
while (!list_empty(dirty_page_list)) {
|
||||
if (kthread_should_stop())
|
||||
return;
|
||||
return 0;
|
||||
|
||||
page = list_first_entry(dirty_page_list, struct sgx_epc_page, list);
|
||||
|
||||
@ -92,12 +96,14 @@ static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
|
||||
} else {
|
||||
/* The page is not yet clean - move to the dirty list. */
|
||||
list_move_tail(&page->list, &dirty);
|
||||
left_dirty++;
|
||||
}
|
||||
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
list_splice(&dirty, dirty_page_list);
|
||||
return left_dirty;
|
||||
}
|
||||
|
||||
static bool sgx_reclaimer_age(struct sgx_epc_page *epc_page)
|
||||
@ -395,10 +401,7 @@ static int ksgxd(void *p)
|
||||
* required for SECS pages, whose child pages blocked EREMOVE.
|
||||
*/
|
||||
__sgx_sanitize_pages(&sgx_dirty_page_list);
|
||||
__sgx_sanitize_pages(&sgx_dirty_page_list);
|
||||
|
||||
/* sanity check: */
|
||||
WARN_ON(!list_empty(&sgx_dirty_page_list));
|
||||
WARN_ON(__sgx_sanitize_pages(&sgx_dirty_page_list));
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
if (try_to_freeze())
|
||||
|
Loading…
x
Reference in New Issue
Block a user