Skip to content

Commit 133e049

Browse files
jarkkojshansendc
authored andcommitted
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: 51ab30e ("x86/sgx: Replace section->init_laundry_list with sgx_dirty_page_list") Reported-by: Paul Menzel <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: Reinette Chatre <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/linux-sgx/[email protected]/T/#u Link: https://lkml.kernel.org/r/[email protected]
1 parent 5515d21 commit 133e049

File tree

1 file changed

+9
-6
lines changed

1 file changed

+9
-6
lines changed

arch/x86/kernel/cpu/sgx/main.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,21 @@ static LIST_HEAD(sgx_dirty_page_list);
4949
* Reset post-kexec EPC pages to the uninitialized state. The pages are removed
5050
* from the input list, and made available for the page allocator. SECS pages
5151
* prepending their children in the input list are left intact.
52+
*
53+
* Return 0 when sanitization was successful or kthread was stopped, and the
54+
* number of unsanitized pages otherwise.
5255
*/
53-
static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
56+
static unsigned long __sgx_sanitize_pages(struct list_head *dirty_page_list)
5457
{
58+
unsigned long left_dirty = 0;
5559
struct sgx_epc_page *page;
5660
LIST_HEAD(dirty);
5761
int ret;
5862

5963
/* dirty_page_list is thread-local, no need for a lock: */
6064
while (!list_empty(dirty_page_list)) {
6165
if (kthread_should_stop())
62-
return;
66+
return 0;
6367

6468
page = list_first_entry(dirty_page_list, struct sgx_epc_page, list);
6569

@@ -92,12 +96,14 @@ static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
9296
} else {
9397
/* The page is not yet clean - move to the dirty list. */
9498
list_move_tail(&page->list, &dirty);
99+
left_dirty++;
95100
}
96101

97102
cond_resched();
98103
}
99104

100105
list_splice(&dirty, dirty_page_list);
106+
return left_dirty;
101107
}
102108

103109
static bool sgx_reclaimer_age(struct sgx_epc_page *epc_page)
@@ -395,10 +401,7 @@ static int ksgxd(void *p)
395401
* required for SECS pages, whose child pages blocked EREMOVE.
396402
*/
397403
__sgx_sanitize_pages(&sgx_dirty_page_list);
398-
__sgx_sanitize_pages(&sgx_dirty_page_list);
399-
400-
/* sanity check: */
401-
WARN_ON(!list_empty(&sgx_dirty_page_list));
404+
WARN_ON(__sgx_sanitize_pages(&sgx_dirty_page_list));
402405

403406
while (!kthread_should_stop()) {
404407
if (try_to_freeze())

0 commit comments

Comments
 (0)