Received: by 2002:a25:b794:0:0:0:0:0 with SMTP id n20csp2763404ybh; Mon, 5 Aug 2019 06:28:28 -0700 (PDT) X-Google-Smtp-Source: APXvYqwX2S0odkVWTg1VcJzi7Ampoip4p8wQuzCyFw9xNEqfbrMFRPt7UGVbFLjB++uK5OlZiWGx X-Received: by 2002:a65:514c:: with SMTP id g12mr136836004pgq.76.1565011708514; Mon, 05 Aug 2019 06:28:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565011708; cv=none; d=google.com; s=arc-20160816; b=GnHXG14Xf9giHUpAZKyw/Y3Vkfji1jyvLKXIXl1qEkQevPbxb3aUgYv9B9iRdM4ZYt J7sdRoXtwmRHbjX7/PqvfZIwA6HpxHi6lCL1Mb84syTvNjoBNoG2kePw1ekw3Ss2+F+m 4XVjH/CUFkSRqHk9y+p/4LOF4R1bgXKKh7lLMChh1X53lkkRDabE96QRfhyqpaBfr3xW xxr9Vc4/aOAV67S0YSiuIMqL1q5V06dUZfUPBpQtxNPIv5WWr14xN+k7p3TcqXK2eQ7n I2w3y7TVk8v7ZTr8bAlOofqqYRp6pZMJbgD/Cu2IjdkPqDRhkNX5H0G8Sk4YBjzCjK/A EQfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=1x5Z6DfOoGDmfVAO7Q7r2tj/lPza3C+HN7e2w+OvqNE=; b=OCnU9SgBiDy5/Ys4hz90BGFPs1aLb/BGHdT0r9cqMTZYf7TJobzTHqgTPgyO8JZvt5 /x5Ccn/5J1EL0MolUJ2pxmjQ+BqrOLwEkUEgGvhwPvcGy3RH6i9oCjDd/O+52Fuk8/kN nC06IXXXdXVvAwVQTpKFS3X1EhkgaeEE8mdFIpk/gP4Ztzrvh3j/k7UtCVd/W6Ox38Cn rTd9ftsG7L48a9HJOkRByTDNMvZwrl+eeVDHHzHS2BSX+n18gQ1o0OFzVnvqh4qS6gPk 5McdiK2ssDEujPv3Nyv5Ka8xJaMu3cflC5LG43iExjppTVVEJMHiwKoio0vd1YBrYm3b vZRg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=gVfeUnkH; 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 1si22047093plz.351.2019.08.05.06.28.13; Mon, 05 Aug 2019 06:28:28 -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; dkim=pass header.i=@kernel.org header.s=default header.b=gVfeUnkH; 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 S1731044AbfHENYi (ORCPT + 99 others); Mon, 5 Aug 2019 09:24:38 -0400 Received: from mail.kernel.org ([198.145.29.99]:33108 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731039AbfHENYe (ORCPT ); Mon, 5 Aug 2019 09:24:34 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 1EB172173C; Mon, 5 Aug 2019 13:24:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1565011473; bh=cSXLFjvwyHw2gAGDjH+6VhM4Ml2vsJ43WmdVDFlFgTA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gVfeUnkHk0kt9LyC7ifSHazZQK9okQRRsUXjvLRi4dHKcP1sYqs7cXOD9sLY83fcT B+04J9iiiOnUIUbQmWlJtKhwrAcobSIizMfUn3Pu+qi32OEKrGXYxsN8LftlYLcFUW TtNWgKLkdHe1vMJMruW0jvw0P6slf3bVe8Nfi4UQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jan Kara , Mel Gorman , Andrew Morton , Linus Torvalds Subject: [PATCH 5.2 101/131] mm: migrate: fix reference check race between __find_get_block() and migration Date: Mon, 5 Aug 2019 15:03:08 +0200 Message-Id: <20190805124958.718102251@linuxfoundation.org> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190805124951.453337465@linuxfoundation.org> References: <20190805124951.453337465@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jan Kara commit ebdf4de5642fb6580b0763158b6b4b791c4d6a4d upstream. buffer_migrate_page_norefs() can race with bh users in the following way: CPU1 CPU2 buffer_migrate_page_norefs() buffer_migrate_lock_buffers() checks bh refs spin_unlock(&mapping->private_lock) __find_get_block() spin_lock(&mapping->private_lock) grab bh ref spin_unlock(&mapping->private_lock) move page do bh work This can result in various issues like lost updates to buffers (i.e. metadata corruption) or use after free issues for the old page. This patch closes the race by holding mapping->private_lock while the mapping is being moved to a new page. Ordinarily, a reference can be taken outside of the private_lock using the per-cpu BH LRU but the references are checked and the LRU invalidated if necessary. The private_lock is held once the references are known so the buffer lookup slow path will spin on the private_lock. Between the page lock and private_lock, it should be impossible for other references to be acquired and updates to happen during the migration. A user had reported data corruption issues on a distribution kernel with a similar page migration implementation as mainline. The data corruption could not be reproduced with this patch applied. A small number of migration-intensive tests were run and no performance problems were noted. [mgorman@techsingularity.net: Changelog, removed tracing] Link: http://lkml.kernel.org/r/20190718090238.GF24383@techsingularity.net Fixes: 89cb0888ca14 "mm: migrate: provide buffer_migrate_page_norefs()" Signed-off-by: Jan Kara Signed-off-by: Mel Gorman Cc: [5.0+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/migrate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) --- a/mm/migrate.c +++ b/mm/migrate.c @@ -771,12 +771,12 @@ recheck_buffers: } bh = bh->b_this_page; } while (bh != head); - spin_unlock(&mapping->private_lock); if (busy) { if (invalidated) { rc = -EAGAIN; goto unlock_buffers; } + spin_unlock(&mapping->private_lock); invalidate_bh_lrus(); invalidated = true; goto recheck_buffers; @@ -809,6 +809,8 @@ recheck_buffers: rc = MIGRATEPAGE_SUCCESS; unlock_buffers: + if (check_refs) + spin_unlock(&mapping->private_lock); bh = head; do { unlock_buffer(bh);