Skip to content

Commit aa5c3aa

Browse files
jarkkojsgregkh
authored andcommitted
x86/sgx: Do not fail on incomplete sanitization on premature stop of ksgxd
commit 133e049 upstream. 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] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 476c188 commit aa5c3aa

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
@@ -46,17 +46,21 @@ static LIST_HEAD(sgx_dirty_page_list);
4646
* Reset post-kexec EPC pages to the uninitialized state. The pages are removed
4747
* from the input list, and made available for the page allocator. SECS pages
4848
* prepending their children in the input list are left intact.
49+
*
50+
* Return 0 when sanitization was successful or kthread was stopped, and the
51+
* number of unsanitized pages otherwise.
4952
*/
50-
static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
53+
static unsigned long __sgx_sanitize_pages(struct list_head *dirty_page_list)
5154
{
55+
unsigned long left_dirty = 0;
5256
struct sgx_epc_page *page;
5357
LIST_HEAD(dirty);
5458
int ret;
5559

5660
/* dirty_page_list is thread-local, no need for a lock: */
5761
while (!list_empty(dirty_page_list)) {
5862
if (kthread_should_stop())
59-
return;
63+
return 0;
6064

6165
page = list_first_entry(dirty_page_list, struct sgx_epc_page, list);
6266

@@ -71,12 +75,14 @@ static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
7175
} else {
7276
/* The page is not yet clean - move to the dirty list. */
7377
list_move_tail(&page->list, &dirty);
78+
left_dirty++;
7479
}
7580

7681
cond_resched();
7782
}
7883

7984
list_splice(&dirty, dirty_page_list);
85+
return left_dirty;
8086
}
8187

8288
static bool sgx_reclaimer_age(struct sgx_epc_page *epc_page)
@@ -427,10 +433,7 @@ static int ksgxd(void *p)
427433
* required for SECS pages, whose child pages blocked EREMOVE.
428434
*/
429435
__sgx_sanitize_pages(&sgx_dirty_page_list);
430-
__sgx_sanitize_pages(&sgx_dirty_page_list);
431-
432-
/* sanity check: */
433-
WARN_ON(!list_empty(&sgx_dirty_page_list));
436+
WARN_ON(__sgx_sanitize_pages(&sgx_dirty_page_list));
434437

435438
while (!kthread_should_stop()) {
436439
if (try_to_freeze())

0 commit comments

Comments
 (0)