From patchwork Tue Nov 13 05:52:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 10679625 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8E2D013BB for ; Tue, 13 Nov 2018 05:52:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 785772A2B7 for ; Tue, 13 Nov 2018 05:52:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 767552A3F9; Tue, 13 Nov 2018 05:52:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB5F42A402 for ; Tue, 13 Nov 2018 05:52:47 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 4201B6B0294; Tue, 13 Nov 2018 00:52:43 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 37B576B0296; Tue, 13 Nov 2018 00:52:43 -0500 (EST) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 269926B0297; Tue, 13 Nov 2018 00:52:43 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-pf1-f200.google.com (mail-pf1-f200.google.com [209.85.210.200]) by kanga.kvack.org (Postfix) with ESMTP id D8EBF6B0294 for ; Tue, 13 Nov 2018 00:52:42 -0500 (EST) Received: by mail-pf1-f200.google.com with SMTP id o28-v6so6356753pfk.10 for ; Mon, 12 Nov 2018 21:52:42 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:dkim-signature:from:to:cc:subject:date :message-id:in-reply-to:references; bh=4rM+zzo7/v/s+SHqVN2wEty6XNaOjBDtJGGjTvQ5XKc=; b=an8QcvksxBxWsirN9X1kT8nXH5qlgT1Me6HJb90cClc7Vr5epKFgNnY/+UQ5BSB4aL Mo5Y//Y0GenNKG/L3mkAJcA9wP+8pGQJBlceRyNiZFJ5PcsFazPaQM4c+nAAsNX+deRx O052tIenvf4U5QMAbFJrKzHj6/gwC4te5GmMchoKpigH4KEXhPQjs4nQapVgKn0PCmGe mqE4PtHrMwqhk9hQeYIlEUzTn5iDCX6X1Sf5AQ0BQ/vUhJwlparmkGr9BcDVIEvV9UpL Y3D+IZuy5yroxp7quFc9HiCXt9+zNx372UIrZDyA769M9qeBF3LwW3eUtaVaS0fdyjpi OLbw== X-Gm-Message-State: AGRZ1gKzjlbT3oY6QqNIS3kZUGmzPLioJSn2TpLIah1qNzCHheWpfVVu CYRyaBx4gqRdjxzplADkDE433PxDG3yybvgG2P5BnGTa9Q8mVAVdasEy7GCe2tl1yTQtusMuqPm YO5aefmQmKHSqYtBHzqopICxWuQf0fz0XnQcYUSjgXBhlSH+z3nlDPIpI5QDCJBQ5zA== X-Received: by 2002:a63:5407:: with SMTP id i7mr3503990pgb.413.1542088362523; Mon, 12 Nov 2018 21:52:42 -0800 (PST) X-Google-Smtp-Source: AJdET5fj5xTGcSgTOTWS3GD/qit4c1kVNQZBhHX/DSBs5WwzlMLDhOkrje21QUXN4TouyxlKZsN6 X-Received: by 2002:a63:5407:: with SMTP id i7mr3503960pgb.413.1542088361699; Mon, 12 Nov 2018 21:52:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542088361; cv=none; d=google.com; s=arc-20160816; b=JQR8Tyfx94VOC2WpxExeXX6S48YAGBb1HdMGTzx9nfOS0AmHq+4MLb5of9gasKjdqa y6613fwRL6rv/Bcb/yjFi2Kar4cXB1CyLC+N+mPCMMXpgD4aTcGSEJQ0XcWSsp82eQhi HaJn3QS7A773SlRwQP/Y64OMfFhEJyVWuPkt2UhcvfiAVpulD5EGohDm8XO04q+Lh8XY xdvLHUeWZL/LbJvIkWRqx1NESqbR+upJe4QsW7cB8iN7/I6D8u4uvdvRWSsX8ghwCQnL S0NFOj6TpeKhxIsVbCclOfIeu0feZbPaUMtohYZS2XkHaYfS744tW3rK2bxn1InfGkR9 3jEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=4rM+zzo7/v/s+SHqVN2wEty6XNaOjBDtJGGjTvQ5XKc=; b=CkHWZGMGAGzuMB8hDraqScwR/yx2+3eWUkQueClb8dqLDZrFRkJ51PYEIuiGxYIB+a stN48BZkpmEcRmBv64WvcSz7GaQqzTxLHKZT9/FO31YzMYjhM9YcawL9BPGGwwhj8Qbb r2ZIjlpCZRvU3SVS4ZilyisMNdoFJrJNhzZZpYwryM5R3g1NJKVOc/0uByTsICvDB6ha iEBcok6rS4LJsVH98JnmejDBoPLN33G2PykxkBpkLsjEE7iOkhXZoUAcMjFbXOQqAMty Iiwgkzy6c+pxROlb7B5+BPUsJvvSe1yUnSl/Oz8vELSq4AD3sI0CiNLRHcL8DqYc7DhF AdaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=qX4G7JJq; spf=pass (google.com: domain of sashal@kernel.org designates 198.145.29.99 as permitted sender) smtp.mailfrom=sashal@kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from mail.kernel.org (mail.kernel.org. [198.145.29.99]) by mx.google.com with ESMTPS id h3si19307674pgi.391.2018.11.12.21.52.41 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 12 Nov 2018 21:52:41 -0800 (PST) Received-SPF: pass (google.com: domain of sashal@kernel.org designates 198.145.29.99 as permitted sender) client-ip=198.145.29.99; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=qX4G7JJq; spf=pass (google.com: domain of sashal@kernel.org designates 198.145.29.99 as permitted sender) smtp.mailfrom=sashal@kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from sasha-vm.mshome.net (unknown [64.114.255.114]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 3EEC42251D; Tue, 13 Nov 2018 05:52:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1542088361; bh=P/0AuPw3ZpCOOANV96befJtEvWk9R1zto4pWPIT1cfg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qX4G7JJqPnDds1PRqeqTqx7l3MD2ulbnFvqk+tRQARfDfreWN5sjOOeP99xGlpnue Lq/JXEEqARMidFDkceTdqDa5ZRX4u2sBb45M+GnYaPBOi8BP4XZuh3+ZYverSBHius zp0BjoDd3tSmHiyBMGzf1p03lfBrFakzTm7YzTns= From: Sasha Levin To: stable@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Andrea Arcangeli , Andrew Morton , Linus Torvalds , Sasha Levin , linux-mm@kvack.org Subject: [PATCH AUTOSEL 4.9 16/17] userfaultfd: allow get_mempolicy(MPOL_F_NODE|MPOL_F_ADDR) to trigger userfaults Date: Tue, 13 Nov 2018 00:52:22 -0500 Message-Id: <20181113055223.79060-16-sashal@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181113055223.79060-1-sashal@kernel.org> References: <20181113055223.79060-1-sashal@kernel.org> X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: Andrea Arcangeli [ Upstream commit 3b9aadf7278d16d7bed4d5d808501065f70898d8 ] get_mempolicy(MPOL_F_NODE|MPOL_F_ADDR) called a get_user_pages that would not be waiting for userfaults before failing and it would hit on a SIGBUS instead. Using get_user_pages_locked/unlocked instead will allow get_mempolicy to allow userfaults to resolve the fault and fill the hole, before grabbing the node id of the page. If the user calls get_mempolicy() with MPOL_F_ADDR | MPOL_F_NODE for an address inside an area managed by uffd and there is no page at that address, the page allocation from within get_mempolicy() will fail because get_user_pages() does not allow for page fault retry required for uffd; the user will get SIGBUS. With this patch, the page fault will be resolved by the uffd and the get_mempolicy() will continue normally. Background: Via code review, previously the syscall would have returned -EFAULT (vm_fault_to_errno), now it will block and wait for an userfault (if it's waken before the fault is resolved it'll still -EFAULT). This way get_mempolicy will give a chance to an "unaware" app to be compliant with userfaults. The reason this visible change is that becoming "userfault compliant" cannot regress anything: all other syscalls including read(2)/write(2) had to become "userfault compliant" long time ago (that's one of the things userfaultfd can do that PROT_NONE and trapping segfaults can't). So this is just one more syscall that become "userfault compliant" like all other major ones already were. This has been happening on virtio-bridge dpdk process which just called get_mempolicy on the guest space post live migration, but before the memory had a chance to be migrated to destination. I didn't run an strace to be able to show the -EFAULT going away, but I've the confirmation of the below debug aid information (only visible with CONFIG_DEBUG_VM=y) going away with the patch: [20116.371461] FAULT_FLAG_ALLOW_RETRY missing 0 [20116.371464] CPU: 1 PID: 13381 Comm: vhost-events Not tainted 4.17.12-200.fc28.x86_64 #1 [20116.371465] Hardware name: LENOVO 20FAS2BN0A/20FAS2BN0A, BIOS N1CET54W (1.22 ) 02/10/2017 [20116.371466] Call Trace: [20116.371473] dump_stack+0x5c/0x80 [20116.371476] handle_userfault.cold.37+0x1b/0x22 [20116.371479] ? remove_wait_queue+0x20/0x60 [20116.371481] ? poll_freewait+0x45/0xa0 [20116.371483] ? do_sys_poll+0x31c/0x520 [20116.371485] ? radix_tree_lookup_slot+0x1e/0x50 [20116.371488] shmem_getpage_gfp+0xce7/0xe50 [20116.371491] ? page_add_file_rmap+0x1a/0x2c0 [20116.371493] shmem_fault+0x78/0x1e0 [20116.371495] ? filemap_map_pages+0x3a1/0x450 [20116.371498] __do_fault+0x1f/0xc0 [20116.371500] __handle_mm_fault+0xe2e/0x12f0 [20116.371502] handle_mm_fault+0xda/0x200 [20116.371504] __get_user_pages+0x238/0x790 [20116.371506] get_user_pages+0x3e/0x50 [20116.371510] kernel_get_mempolicy+0x40b/0x700 [20116.371512] ? vfs_write+0x170/0x1a0 [20116.371515] __x64_sys_get_mempolicy+0x21/0x30 [20116.371517] do_syscall_64+0x5b/0x160 [20116.371520] entry_SYSCALL_64_after_hwframe+0x44/0xa9 The above harmless debug message (not a kernel crash, just a dump_stack()) is shown with CONFIG_DEBUG_VM=y to more quickly identify and improve kernel spots that may have to become "userfaultfd compliant" like this one (without having to run an strace and search for syscall misbehavior). Spots like the above are more closer to a kernel bug for the non-cooperative usages that Mike focuses on, than for for dpdk qemu-cooperative usages that reproduced it, but it's still nicer to get this fixed for dpdk too. The part of the patch that caused me to think is only the implementation issue of mpol_get, but it looks like it should work safe no matter the kind of mempolicy structure that is (the default static policy also starts at 1 so it'll go to 2 and back to 1 without crashing everything at 0). [rppt@linux.vnet.ibm.com: changelog addition] http://lkml.kernel.org/r/20180904073718.GA26916@rapoport-lnx Link: http://lkml.kernel.org/r/20180831214848.23676-1-aarcange@redhat.com Signed-off-by: Andrea Arcangeli Reported-by: Maxime Coquelin Tested-by: Dr. David Alan Gilbert Reviewed-by: Mike Rapoport Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- mm/mempolicy.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 69c4a0c92ebb..625122adefe0 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -845,16 +845,19 @@ static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes) } } -static int lookup_node(unsigned long addr) +static int lookup_node(struct mm_struct *mm, unsigned long addr) { struct page *p; int err; - err = get_user_pages(addr & PAGE_MASK, 1, 0, &p, NULL); + int locked = 1; + err = get_user_pages_locked(addr & PAGE_MASK, 1, 0, &p, &locked); if (err >= 0) { err = page_to_nid(p); put_page(p); } + if (locked) + up_read(&mm->mmap_sem); return err; } @@ -865,7 +868,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, int err; struct mm_struct *mm = current->mm; struct vm_area_struct *vma = NULL; - struct mempolicy *pol = current->mempolicy; + struct mempolicy *pol = current->mempolicy, *pol_refcount = NULL; if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR|MPOL_F_MEMS_ALLOWED)) @@ -905,7 +908,16 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, if (flags & MPOL_F_NODE) { if (flags & MPOL_F_ADDR) { - err = lookup_node(addr); + /* + * Take a refcount on the mpol, lookup_node() + * wil drop the mmap_sem, so after calling + * lookup_node() only "pol" remains valid, "vma" + * is stale. + */ + pol_refcount = pol; + vma = NULL; + mpol_get(pol); + err = lookup_node(mm, addr); if (err < 0) goto out; *policy = err; @@ -940,7 +952,9 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, out: mpol_cond_put(pol); if (vma) - up_read(¤t->mm->mmap_sem); + up_read(&mm->mmap_sem); + if (pol_refcount) + mpol_put(pol_refcount); return err; }