Received: by 2002:a25:683:0:0:0:0:0 with SMTP id 125csp971703ybg; Wed, 10 Jun 2020 19:47:17 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyxwjPF+qd9zTTAjMmwbaISUvP80FE6x4kznym8SnsvOoNpK9gVyQcS4PBEbWTD1YVQc+KM X-Received: by 2002:a05:6402:17ce:: with SMTP id s14mr4965592edy.53.1591843637446; Wed, 10 Jun 2020 19:47:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591843637; cv=none; d=google.com; s=arc-20160816; b=PwGyvnkE15c0LZ3+RiXmTiyYFJMvSiw2pQ5GSV76KFVsXWwuz9+57bh8iLaaZ8rmUB ScRap9/7jlmooZAfnaSO1uJxep1XeMfKEI3N3ackHk1Eviqanzet+9N0lESMt1ASO5PT 0JMuopOSJYqtqo6FHWq2lJSV9z173hoJGNyjAtn5AKrDwLYyUfLTbnuQPuQhkyTEQaKm X1zXiAo2wmFkroax3sdv6kiFFa3O/cYaBFjcHJZOQzdCTDluSTNxFweh+3l3r4oRsgzt JsRLJnPLSWXFFz/u1EiaG76+JDr9aVr0HwxM3X8sIXqRiwNfFmMO8bNr/Q0UBPbOmAUh ZHpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=Aoa650UL3LLeSoxF3Lytz3A1uN96L5lJGjZkawSHlwA=; b=KpfTP9v+RKdvDokb12q2EUnmZcKZhxVQueokKrozf7XHD3r8ensXHQF5B+t617MGrW XzIdvnpyWXjaBdB/aqMlVVQRamfhpLiaJN6RVeBbk7/ZVphE7WaboGU/mv+MJoCT/eAM sOJlcmgEMhW4U+RHDJ8cBH6eYyDVZs70NQkkQq2jmY0lQHV2W5yIIZHDxwAbdwESn3Y8 FNwPT7orcA7nLnSb1xWqDYiyn0PD9jdweoR2Hny7dZy044xGb+grmL6eoAw8c+zLIMu8 lKZYWIwVYHE1ua99iNoukO2AZCScS26kr06vVo3EDuffPBH6NwseMuT6jvW5d54SvrJb NJ8w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id k14si1024025ejq.440.2020.06.10.19.46.54; Wed, 10 Jun 2020 19:47:17 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726387AbgFKCpM (ORCPT + 99 others); Wed, 10 Jun 2020 22:45:12 -0400 Received: from mail109.syd.optusnet.com.au ([211.29.132.80]:49777 "EHLO mail109.syd.optusnet.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726279AbgFKCpM (ORCPT ); Wed, 10 Jun 2020 22:45:12 -0400 Received: from dread.disaster.area (pa49-180-124-177.pa.nsw.optusnet.com.au [49.180.124.177]) by mail109.syd.optusnet.com.au (Postfix) with ESMTPS id 5EC80D79956; Thu, 11 Jun 2020 12:45:07 +1000 (AEST) Received: from dave by dread.disaster.area with local (Exim 4.92.3) (envelope-from ) id 1jjDDD-0002Sa-48; Thu, 11 Jun 2020 12:45:03 +1000 Date: Thu, 11 Jun 2020 12:45:03 +1000 From: Dave Chinner To: Yu Kuai Cc: darrick.wong@oracle.com, linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org, yi.zhang@huawei.com Subject: [PATCH] xfs: fix use-after-free on CIL context on shutdown Message-ID: <20200611024503.GR2040@dread.disaster.area> References: <20200611013952.2589997-1-yukuai3@huawei.com> <20200611022848.GQ2040@dread.disaster.area> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200611022848.GQ2040@dread.disaster.area> User-Agent: Mutt/1.10.1 (2018-07-13) X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.3 cv=X6os11be c=1 sm=1 tr=0 a=k3aV/LVJup6ZGWgigO6cSA==:117 a=k3aV/LVJup6ZGWgigO6cSA==:17 a=kj9zAlcOel0A:10 a=nTHF0DUjJn0A:10 a=20KFwNOVAAAA:8 a=i0EeH86SAAAA:8 a=83KKqrmkPyvGHRv_7b8A:9 a=CjuIK1q_8ugA:10 a=pHzHmUro8NiASowvMSCR:22 a=n87TN5wuljxrRezIQYnT:22 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Dave Chinner xlog_wait() on the CIL context can reference a freed context if the waiter doesn't get scheduled before the CIL context is freed. This can happen when a task is on the hard throttle and the CIL push aborts due to a shutdown. This was detected by generic/019: thread 1 thread 2 __xfs_trans_commit xfs_log_commit_cil xlog_wait schedule xlog_cil_push_work wake_up_all xlog_cil_committed kmem_free remove_wait_queue spin_lock_irqsave --> UAF Fix it by moving the wait queue to the CIL rather than keeping it in in the CIL context that gets freed on push completion. Because the wait queue is now independent of the CIL context and we might have multiple contexts in flight at once, only wake the waiters on the push throttle when the context we are pushing is over the hard throttle size threshold. Fixes: 0e7ab7efe7745 ("xfs: Throttle commits on delayed background CIL push") Reported-by: Yu Kuai Signed-off-by: Dave Chinner --- fs/xfs/xfs_log_cil.c | 10 +++++----- fs/xfs/xfs_log_priv.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index b43f0e8f43f2e..9ed90368ab311 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -671,7 +671,8 @@ xlog_cil_push_work( /* * Wake up any background push waiters now this context is being pushed. */ - wake_up_all(&ctx->push_wait); + if (ctx->space_used >= XLOG_CIL_BLOCKING_SPACE_LIMIT(log)) + wake_up_all(&cil->xc_push_wait); /* * Check if we've anything to push. If there is nothing, then we don't @@ -743,13 +744,12 @@ xlog_cil_push_work( /* * initialise the new context and attach it to the CIL. Then attach - * the current context to the CIL committing lsit so it can be found + * the current context to the CIL committing list so it can be found * during log forces to extract the commit lsn of the sequence that * needs to be forced. */ INIT_LIST_HEAD(&new_ctx->committing); INIT_LIST_HEAD(&new_ctx->busy_extents); - init_waitqueue_head(&new_ctx->push_wait); new_ctx->sequence = ctx->sequence + 1; new_ctx->cil = cil; cil->xc_ctx = new_ctx; @@ -937,7 +937,7 @@ xlog_cil_push_background( if (cil->xc_ctx->space_used >= XLOG_CIL_BLOCKING_SPACE_LIMIT(log)) { trace_xfs_log_cil_wait(log, cil->xc_ctx->ticket); ASSERT(cil->xc_ctx->space_used < log->l_logsize); - xlog_wait(&cil->xc_ctx->push_wait, &cil->xc_push_lock); + xlog_wait(&cil->xc_push_wait, &cil->xc_push_lock); return; } @@ -1216,12 +1216,12 @@ xlog_cil_init( INIT_LIST_HEAD(&cil->xc_committing); spin_lock_init(&cil->xc_cil_lock); spin_lock_init(&cil->xc_push_lock); + init_waitqueue_head(&cil->xc_push_wait); init_rwsem(&cil->xc_ctx_lock); init_waitqueue_head(&cil->xc_commit_wait); INIT_LIST_HEAD(&ctx->committing); INIT_LIST_HEAD(&ctx->busy_extents); - init_waitqueue_head(&ctx->push_wait); ctx->sequence = 1; ctx->cil = cil; cil->xc_ctx = ctx; diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index ec22c7a3867f1..75a62870b63af 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -240,7 +240,6 @@ struct xfs_cil_ctx { struct xfs_log_vec *lv_chain; /* logvecs being pushed */ struct list_head iclog_entry; struct list_head committing; /* ctx committing list */ - wait_queue_head_t push_wait; /* background push throttle */ struct work_struct discard_endio_work; }; @@ -274,6 +273,7 @@ struct xfs_cil { wait_queue_head_t xc_commit_wait; xfs_lsn_t xc_current_sequence; struct work_struct xc_push_work; + wait_queue_head_t xc_push_wait; /* background push throttle */ } ____cacheline_aligned_in_smp; /*