From patchwork Mon Nov 26 17:34:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Arcangeli X-Patchwork-Id: 10698859 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 AC1D213BF for ; Mon, 26 Nov 2018 17:35:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 94D1C28630 for ; Mon, 26 Nov 2018 17:35:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8591729F76; Mon, 26 Nov 2018 17:35:03 +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=-2.9 required=2.0 tests=BAYES_00,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 8795228630 for ; Mon, 26 Nov 2018 17:35:01 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 93B466B42CA; Mon, 26 Nov 2018 12:34:58 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 8C45B6B42CB; Mon, 26 Nov 2018 12:34:58 -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 75DDE6B42CE; Mon, 26 Nov 2018 12:34:58 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) by kanga.kvack.org (Postfix) with ESMTP id 3E8A16B42CA for ; Mon, 26 Nov 2018 12:34:58 -0500 (EST) Received: by mail-qt1-f198.google.com with SMTP id b16so17025519qtc.22 for ; Mon, 26 Nov 2018 09:34:58 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:from:to:cc :subject:date:message-id:in-reply-to:references; bh=6n4GNHlA9ZS4Y3E0x8zmJPG1InhQ9JnR+HZCRoVwkGw=; b=MiWPl9N+B9rOnK1rTpxXjFkmoOf+mSGtaITP1dMiwT10zSM16kyQHVRkruYashAxl6 jo53JgWItYvbThG9j4BY/yaZcqC1fY4JHfrb6rEPDB+5Ni2Y5dCkkow+ajvssi6qJzHE LOJYMOhuGRPdtqNlIfQUnMzYGOVb5QjgXdZ8iOJKoN8uJN8RF1rRvE7Y9hsEuEUTvEgI dj+ty0ouLieWEWsMlDkGE01BZ3UDTz8jBhLpsuzjhhjLMtJBwglPR/7lv84V6LNbvJ7q Qjb8k7OTX6V0C+MgxFXzPIgvMA68ZpAb3xnbtTfsBwu7KWXncfmV21KY/wqn35ahbqCF zmeg== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of aarcange@redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=aarcange@redhat.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Gm-Message-State: AA+aEWZrQTkD+QgmX3Ky+NRKUJsXr4XyPr9Bb7mWQxaYZQKk+n0mF0rA SC79M37FkZ0KlEPQeOBVnR84mKLlXeGroBUJDiVC/Bfbtr3o1Meims6y5uavYx9v42qygcCP/PA jz2lJCBOPsA9sQfXDhzVa5rfSujDni0EWJXFsxk/OeN0FIHyMr8+gU87V7vbXXhvMYA== X-Received: by 2002:a0c:afd1:: with SMTP id t17mr26948103qvc.93.1543253698004; Mon, 26 Nov 2018 09:34:58 -0800 (PST) X-Google-Smtp-Source: AFSGD/XxFJwYoyKSDtyZvMEOm/ij3/OsHHn244SsCifgLfgp6JwNZswqWGV1IkzeiF/L6dBPDS9t X-Received: by 2002:a0c:afd1:: with SMTP id t17mr26948059qvc.93.1543253697333; Mon, 26 Nov 2018 09:34:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543253697; cv=none; d=google.com; s=arc-20160816; b=ysLQHLuSau5wS3HLt22CKdR03MT7EdlX9D9B6SR3ROd6lOzqnmiCcM4LSh53qPAJPg W9BKG5+byDPBoM+FTJoSy66fgAzcBUR878AN+LfLaKIBUWSOhYcMv9IjZdhWcIoAF9Ho wKTw7GR07KYtnAsladLz8uBB2YjSSbpxwHSfluSn2B6L1ZkLTM/tLgbS5rLLBK0b1LCa KmMK/dvB94RoTsVQ8MN6Q4xHQb0h23etNIdc414KkDxJpL1O9gKagcZiQdvFeGLMP9yH H8qLySaJQBf/KTMrA/PiV9Ax4nCssWdYf/8vwAWwS7c9QYwNDhWA9gny5HsRR8YUPqZs uwcA== 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; bh=6n4GNHlA9ZS4Y3E0x8zmJPG1InhQ9JnR+HZCRoVwkGw=; b=krHsU26xZfnpqv9rlbLAXEzJlmfBwk6K3zlO3rKEMnDvaaURPz8wbNqvxzSHyWbPGU ju1yep7anMEf8UOZplxqkl3wNwpekNgtkxDHr3QHCjjuS/oCb5HI6T9N7PpIeBWfG+hS Y8TdQqqfshH3Bv08iDI/thoEorOYb3tmsQMnV3t7e5NRZ3xizwCS2o/29xcHK6UD2nON lZ2bPWzhAKhXmuXhuRhGdeckVU2IgsLAgKaeiwjFa1EIrbb9iQ8yvs+JlFYjo/HfCncn Rjv6cGy+HjcGTvlCnXKJtrx0IoTfdDTJd74qRkWvc569pwjwKy2NCJH5cdQvu7ag8mez bgSQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of aarcange@redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=aarcange@redhat.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from mx1.redhat.com (mx1.redhat.com. [209.132.183.28]) by mx.google.com with ESMTPS id q15si796478qti.20.2018.11.26.09.34.56 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Nov 2018 09:34:57 -0800 (PST) Received-SPF: pass (google.com: domain of aarcange@redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; Authentication-Results: mx.google.com; spf=pass (google.com: domain of aarcange@redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=aarcange@redhat.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CCF8853F6; Mon, 26 Nov 2018 17:34:55 +0000 (UTC) Received: from sky.random (ovpn-120-160.rdu2.redhat.com [10.10.120.160]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 481EA58B1; Mon, 26 Nov 2018 17:34:53 +0000 (UTC) From: Andrea Arcangeli To: Andrew Morton Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Hugh Dickins , Mike Rapoport , Mike Kravetz , Jann Horn , Peter Xu , "Dr. David Alan Gilbert" Subject: [PATCH 4/5] userfaultfd: shmem: add i_size checks Date: Mon, 26 Nov 2018 12:34:51 -0500 Message-Id: <20181126173452.26955-5-aarcange@redhat.com> In-Reply-To: <20181126173452.26955-1-aarcange@redhat.com> References: <20181126173452.26955-1-aarcange@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 26 Nov 2018 17:34:56 +0000 (UTC) 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 With MAP_SHARED: recheck the i_size after taking the PT lock, to serialize against truncate with the PT lock. Delete the page from the pagecache if the i_size_read check fails. With MAP_PRIVATE: check the i_size after the PT lock before mapping anonymous memory or zeropages into the MAP_PRIVATE shmem mapping. A mostly irrelevant cleanup: like we do the delete_from_page_cache() pagecache removal after dropping the PT lock, the PT lock is a spinlock so drop it before the sleepable page lock. Reviewed-by: Mike Rapoport Reviewed-by: Hugh Dickins Reported-by: Jann Horn Fixes: 4c27fe4c4c84 ("userfaultfd: shmem: add shmem_mcopy_atomic_pte for userfaultfd support") Cc: stable@vger.kernel.org Signed-off-by: Andrea Arcangeli Reviewed-by: Mike Rapoport Reviewed-by: Hugh Dickins Reported-by: Jann Horn Signed-off-by: Andrea Arcangeli Signed-off-by: Mike Rapoport --- mm/shmem.c | 18 ++++++++++++++++-- mm/userfaultfd.c | 26 ++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 353287412c25..c3ece7a51949 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2214,6 +2214,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm, struct page *page; pte_t _dst_pte, *dst_pte; int ret; + pgoff_t offset, max_off; ret = -ENOMEM; if (!shmem_inode_acct_block(inode, 1)) @@ -2251,6 +2252,12 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm, __SetPageSwapBacked(page); __SetPageUptodate(page); + ret = -EFAULT; + offset = linear_page_index(dst_vma, dst_addr); + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + if (unlikely(offset >= max_off)) + goto out_release; + ret = mem_cgroup_try_charge_delay(page, dst_mm, gfp, &memcg, false); if (ret) goto out_release; @@ -2266,8 +2273,14 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm, if (dst_vma->vm_flags & VM_WRITE) _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte)); - ret = -EEXIST; dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl); + + ret = -EFAULT; + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + if (unlikely(offset >= max_off)) + goto out_release_uncharge_unlock; + + ret = -EEXIST; if (!pte_none(*dst_pte)) goto out_release_uncharge_unlock; @@ -2285,13 +2298,14 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm, /* No need to invalidate - it was non-present before */ update_mmu_cache(dst_vma, dst_addr, dst_pte); - unlock_page(page); pte_unmap_unlock(dst_pte, ptl); + unlock_page(page); ret = 0; out: return ret; out_release_uncharge_unlock: pte_unmap_unlock(dst_pte, ptl); + delete_from_page_cache(page); out_release_uncharge: mem_cgroup_cancel_charge(page, memcg, false); out_release: diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 43cf314cfddd..458acda96f20 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -33,6 +33,8 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm, void *page_kaddr; int ret; struct page *page; + pgoff_t offset, max_off; + struct inode *inode; if (!*pagep) { ret = -ENOMEM; @@ -73,8 +75,17 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm, if (dst_vma->vm_flags & VM_WRITE) _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte)); - ret = -EEXIST; dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl); + if (dst_vma->vm_file) { + /* the shmem MAP_PRIVATE case requires checking the i_size */ + inode = dst_vma->vm_file->f_inode; + offset = linear_page_index(dst_vma, dst_addr); + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + ret = -EFAULT; + if (unlikely(offset >= max_off)) + goto out_release_uncharge_unlock; + } + ret = -EEXIST; if (!pte_none(*dst_pte)) goto out_release_uncharge_unlock; @@ -108,11 +119,22 @@ static int mfill_zeropage_pte(struct mm_struct *dst_mm, pte_t _dst_pte, *dst_pte; spinlock_t *ptl; int ret; + pgoff_t offset, max_off; + struct inode *inode; _dst_pte = pte_mkspecial(pfn_pte(my_zero_pfn(dst_addr), dst_vma->vm_page_prot)); - ret = -EEXIST; dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl); + if (dst_vma->vm_file) { + /* the shmem MAP_PRIVATE case requires checking the i_size */ + inode = dst_vma->vm_file->f_inode; + offset = linear_page_index(dst_vma, dst_addr); + max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + ret = -EFAULT; + if (unlikely(offset >= max_off)) + goto out_unlock; + } + ret = -EEXIST; if (!pte_none(*dst_pte)) goto out_unlock; set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte);