Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp2308552imm; Thu, 7 Jun 2018 08:32:41 -0700 (PDT) X-Google-Smtp-Source: ADUXVKIR9vmj/JD+KsLM4kdHIllulBAJsdO0Lx9+9n6WIVCdoxj05wi6hGpCiM8pAALloaQRUpsD X-Received: by 2002:a63:2bc4:: with SMTP id r187-v6mr1976599pgr.231.1528385561198; Thu, 07 Jun 2018 08:32:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528385561; cv=none; d=google.com; s=arc-20160816; b=YgyYLfOOZCfgL7wEYCaXQu6B2bwJ+GRxByiJDlktE3A2rtMQsCfGZkE4x4kUvN/nZG 0lsXWdCA+D/LfgEEQvICvtEsiWARCtKa5Haql7uEJ/bYFVMNf4qeGsA0zp+5jT3mfzG1 D4FnMhlrAjlRufYJ5xIcL0uJWnksKFKHbp1H+4XDDYesPCPHr7WOTsb/BnXg/IjrkQSv XmztvlvQ65TVeL2t1rDUZZx5EiBgRjcl2GdfnZnxDzhh/IDOHkZK1ksvW/c5yPE7mFmD EnSJbpA9tGBdqnOlyFDCxIK104aBgXIOuHJB1NAxg/HcDn0RUF3wBts7LbSlxwjw/8gx NOXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition :arc-authentication-results; bh=xOg2PCg9heB/PKA9E2KuU+1JQZx/biRKS9/2Ow70omA=; b=zBOsrOas0gQCiyUjfkoFHiND6xQXXf1TFEqqGLNP1/7mDSu+izF0ZGJ2HdsowvEalV 9a6mBhe061rQfBbVgUaMusD/+RsP9IWBrYUrgfmAVIeJtjgB7vd39b910wQzC2mNYip/ TFGvksCWPjIV90sQC5yPauH6QslnjeZquEaWIDZR2LdzOBl9llbMG+MDblghDlg+KMPs pSZETVVx3qgepQ8OnIoTFlvLlOaGasinJkchrLeMZDq+NZqBeZTMLYf77+tWnElTcmF9 roceZ9/jMJJCS2trX3GJg9uOW+fFjZoW78l3QboDhNEtSTUpMShcagWOtSAQ5gxKg+0V bw0A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n2-v6si55058625plk.433.2018.06.07.08.32.26; Thu, 07 Jun 2018 08:32:41 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933426AbeFGPbS (ORCPT + 99 others); Thu, 7 Jun 2018 11:31:18 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:40974 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935190AbeFGOyC (ORCPT ); Thu, 7 Jun 2018 10:54:02 -0400 Received: from [148.252.241.226] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1fQvbG-0005Zi-69; Thu, 07 Jun 2018 15:09:14 +0100 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1fQvbC-0003FT-Qz; Thu, 07 Jun 2018 15:09:10 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Jann Horn" , "Kent Overstreet" , "Tejun Heo" , "Linus Torvalds" Date: Thu, 07 Jun 2018 15:05:21 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 357/410] fs/aio: Add explicit RCU grace period when freeing kioctx In-Reply-To: X-SA-Exim-Connect-IP: 148.252.241.226 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.57-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Tejun Heo commit a6d7cff472eea87d96899a20fa718d2bab7109f3 upstream. While fixing refcounting, e34ecee2ae79 ("aio: Fix a trinity splat") incorrectly removed explicit RCU grace period before freeing kioctx. The intention seems to be depending on the internal RCU grace periods of percpu_ref; however, percpu_ref uses a different flavor of RCU, sched-RCU. This can lead to kioctx being freed while RCU read protected dereferences are still in progress. Fix it by updating free_ioctx() to go through call_rcu() explicitly. v2: Comment added to explain double bouncing. Signed-off-by: Tejun Heo Reported-by: Jann Horn Fixes: e34ecee2ae79 ("aio: Fix a trinity splat") Cc: Kent Overstreet Cc: Linus Torvalds Signed-off-by: Ben Hutchings --- fs/aio.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) --- a/fs/aio.c +++ b/fs/aio.c @@ -115,7 +115,8 @@ struct kioctx { struct page **ring_pages; long nr_pages; - struct work_struct free_work; + struct rcu_head free_rcu; + struct work_struct free_work; /* see free_ioctx() */ /* * signals when all in-flight requests are done @@ -512,6 +513,12 @@ static int kiocb_cancel(struct kiocb *ki return cancel(kiocb); } +/* + * free_ioctx() should be RCU delayed to synchronize against the RCU + * protected lookup_ioctx() and also needs process context to call + * aio_free_ring(), so the double bouncing through kioctx->free_rcu and + * ->free_work. + */ static void free_ioctx(struct work_struct *work) { struct kioctx *ctx = container_of(work, struct kioctx, free_work); @@ -523,6 +530,14 @@ static void free_ioctx(struct work_struc kmem_cache_free(kioctx_cachep, ctx); } +static void free_ioctx_rcufn(struct rcu_head *head) +{ + struct kioctx *ctx = container_of(head, struct kioctx, free_rcu); + + INIT_WORK(&ctx->free_work, free_ioctx); + schedule_work(&ctx->free_work); +} + static void free_ioctx_reqs(struct percpu_ref *ref) { struct kioctx *ctx = container_of(ref, struct kioctx, reqs); @@ -531,8 +546,8 @@ static void free_ioctx_reqs(struct percp if (ctx->rq_wait && atomic_dec_and_test(&ctx->rq_wait->count)) complete(&ctx->rq_wait->comp); - INIT_WORK(&ctx->free_work, free_ioctx); - schedule_work(&ctx->free_work); + /* Synchronize against RCU protected table->table[] dereferences */ + call_rcu(&ctx->free_rcu, free_ioctx_rcufn); } /* @@ -754,7 +769,7 @@ static int kill_ioctx(struct mm_struct * table->table[ctx->id] = NULL; spin_unlock(&mm->ioctx_lock); - /* percpu_ref_kill() will do the necessary call_rcu() */ + /* free_ioctx_reqs() will do the necessary RCU synchronization */ wake_up_all(&ctx->wait); /*