From: Jarkko Sakkinen <jarkko@xxxxxxxxxx> The most trivial example of a race condition can be demonstrated with this example where mm_list contains just one entry: CPU A CPU B sgx_release() sgx_mmu_notifier_release() list_del_rcu() sgx_encl_release() synchronize_srcu() cleanup_srcu_struct() To fix this, call synchronize_srcu() before checking whether mm_list is empty in sgx_release(). Cc: stable@xxxxxxxxxxxxxxx Fixes: 1728ab54b4be ("x86/sgx: Add a page reclaimer") Suggested-by: Sean Christopherson <seanjc@xxxxxxxxxx> Suggested-by: Haitao Huang <haitao.huang@xxxxxxxxxxxxxxx> Signed-off-by: Jarkko Sakkinen <jarkko@xxxxxxxxxx> --- v4: - Rewrite the commit message. - Just change the call order. *_expedited() is out of scope for this bug fix. v3: Fine-tuned tags, and added missing change log for v2. v2: Switch to synchronize_srcu_expedited(). arch/x86/kernel/cpu/sgx/driver.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/driver.c index f2eac41bb4ff..53056345f5f8 100644 --- a/arch/x86/kernel/cpu/sgx/driver.c +++ b/arch/x86/kernel/cpu/sgx/driver.c @@ -65,11 +65,16 @@ static int sgx_release(struct inode *inode, struct file *file) spin_unlock(&encl->mm_lock); + /* + * The call is need even if the list empty, because sgx_encl_mmu_notifier_release() + * could have initiated a new grace period. + */ + synchronize_srcu(&encl->srcu); + /* The enclave is no longer mapped by any mm. */ if (!encl_mm) break; - synchronize_srcu(&encl->srcu); mmu_notifier_unregister(&encl_mm->mmu_notifier, encl_mm->mm); kfree(encl_mm); } -- 2.29.2