From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 909A6CA9ECF for ; Mon, 4 Nov 2019 06:42:23 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 2C05B20656 for ; Mon, 4 Nov 2019 06:42:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=126.com header.i=@126.com header.b="dMc2POIr" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2C05B20656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=126.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id A3BBD6B0005; Mon, 4 Nov 2019 01:42:22 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 9ECDD6B0006; Mon, 4 Nov 2019 01:42:22 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 903286B0007; Mon, 4 Nov 2019 01:42:22 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0095.hostedemail.com [216.40.44.95]) by kanga.kvack.org (Postfix) with ESMTP id 778DF6B0005 for ; Mon, 4 Nov 2019 01:42:22 -0500 (EST) Received: from smtpin20.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay05.hostedemail.com (Postfix) with SMTP id 23B5F181AEF10 for ; Mon, 4 Nov 2019 06:42:22 +0000 (UTC) X-FDA: 76117650924.20.pipe31_6bd92ae910a4c X-HE-Tag: pipe31_6bd92ae910a4c X-Filterd-Recvd-Size: 6374 Received: from m15-113.126.com (m15-113.126.com [220.181.15.113]) by imf10.hostedemail.com (Postfix) with ESMTP for ; Mon, 4 Nov 2019 06:42:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; s=s110527; h=From:Subject:Date:Message-Id:MIME-Version; bh=pMijh oDJEtCaQ3Zjfe5qkteiGQANRfLuSATLAh2HPy0=; b=dMc2POIrXVOGRbIEZrMGo 5nITS9iV08OwVlRkUa31UeFyk3Q9o032rkgDxk6jdkqoY1LlmpkOKPQn2fBpvham TQdQc82tUr0UntGlbwdsJ8BOPmyvFsezs1pwVOYPi02P5qsaofSG/s+zCgDR0GUf +qR/zDQLgzQxowOqT8joAM= Received: from N-20L6PF1KTYA2.nsn-intra.net (unknown [112.17.245.45]) by smtp3 (Coremail) with SMTP id DcmowADXJzcoyL9dgpfhDQ--.41074S2; Mon, 04 Nov 2019 14:41:47 +0800 (CST) From: Li Xinhai To: linux-mm@kvack.org Cc: Li Xinhai , akpm@linux-foundation.org, n-horiguchi@ah.jp.nec.com, mhocko@suse.com, vbabka@suse.cz, hughd@google.com, linux-man@vger.kernel.org, linux-api@vger.kernel.org, Li Xinhai Subject: [PATCH v3] mm: Fix checking unmapped holes for mbind Date: Mon, 4 Nov 2019 14:40:52 +0800 Message-Id: <20191104064052.3444-1-lixinhai_lxh@126.com> X-Mailer: git-send-email 2.22.0.windows.1 MIME-Version: 1.0 X-CM-TRANSID:DcmowADXJzcoyL9dgpfhDQ--.41074S2 X-Coremail-Antispam: 1Uf129KBjvJXoWxJFWUXF4Dtw1rZr1fXr18Xwb_yoWrZF1fpF WfKw1Yva17K3ySq3sakFyqkry5trn2g3y0yF4xtwn5Zr15trWYq34xKrWYqFWYyrykZF4a yFsI9w4Duw4UZFDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07bjwZcUUUUU= X-Originating-IP: [112.17.245.45] X-CM-SenderInfo: pol0x0pkdlszl0k6ij2wof0z/1tbiYAxj1VpD9+M3UgAAsy Content-Transfer-Encoding: quoted-printable 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: From: Li Xinhai mbind() is required to report EFAULT if range, specified by addr and len, contains unmapped holes. In current implementation, below rules are appli= ed for this checking: 1 Unmapped holes at any part of the specified range should be reported as EFAULT if mbind() for none MPOL_DEFAULT cases; 2 Unmapped holes at any part of the specified range should be ignored (do not reprot EFAULT) if mbind() for MPOL_DEFAULT case; 3 The whole range in an unmapped hole should be reported as EFAULT; Note that rule 2 does not fullfill the mbind() API definition, but since that behavior has existed for long days (refer the usage of internal flag MPOL_MF_DISCONTIG_OK), this patch does not plan to change it. Cases do not follow those rules and been fixed by this patch are: case_1: unmapped hole at tail side of the sepcified range when mbind() fo= r non MPOL_DEFAULT cases, EFAULT is not reported (conflicts rule 1)= . [ hole ][ vma ][ hole ] [ range ] case_2: unmapped hole at head side of the specified range when mbind() fo= r MPOL_DEFAULT case, EFAULT is reported (conflicts rule 2). [ hole ][ vma ][ hole ] [ range ] Fixes: 9d8cebd4bcd7 ("mm: fix mbind vma merge problem") Fixes: 6f4576e3687b ("mempolicy: apply page table walker on queue_pages_r= ange()") Fixes: 48684a65b4e3 ("mm: pagewalk: fix misbehavior of walk_page_range fo= r vma(VM_PFNMAP)") Signed-off-by: Li Xinhai Cc: Andrew Morton Cc: Naoya Horiguchi Cc: Michal Hocko Cc: Vlastimil Babka Cc: linux-man --- Changes v2->v3: - Add more details in change log; - Check holes in .test_walk() and after call walk_page_range() mm/mempolicy.c | 52 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 4ae967b..b2e10bf 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -410,7 +410,9 @@ struct queue_pages { struct list_head *pagelist; unsigned long flags; nodemask_t *nmask; - struct vm_area_struct *prev; + unsigned long start; + struct vm_area_struct *first; + struct vm_area_struct *last; }; =20 /* @@ -618,6 +620,21 @@ static int queue_pages_test_walk(unsigned long start= , unsigned long end, unsigned long endvma =3D vma->vm_end; unsigned long flags =3D qp->flags; =20 + /* range check first */ + VM_BUG_ON((vma->vm_start > start) || (vma->vm_end < end)); + + if (!qp->first) { + qp->first =3D vma; + if (!(flags & MPOL_MF_DISCONTIG_OK) && + (qp->start < vma->vm_start)) + /* hole at head side of range */ + return -EFAULT; + } else if (!(flags & MPOL_MF_DISCONTIG_OK) && + (vma->vm_prev->vm_end < vma->vm_start)) + /* hole at middle of range */ + return -EFAULT; + qp->last =3D vma; + /* * Need check MPOL_MF_STRICT to return -EIO if possible * regardless of vma_migratable @@ -628,17 +645,6 @@ static int queue_pages_test_walk(unsigned long start= , unsigned long end, =20 if (endvma > end) endvma =3D end; - if (vma->vm_start > start) - start =3D vma->vm_start; - - if (!(flags & MPOL_MF_DISCONTIG_OK)) { - if (!vma->vm_next && vma->vm_end < end) - return -EFAULT; - if (qp->prev && qp->prev->vm_end < vma->vm_start) - return -EFAULT; - } - - qp->prev =3D vma; =20 if (flags & MPOL_MF_LAZY) { /* Similar to task_numa_work, skip inaccessible VMAs */ @@ -679,14 +685,29 @@ static int queue_pages_test_walk(unsigned long star= t, unsigned long end, nodemask_t *nodes, unsigned long flags, struct list_head *pagelist) { + int err; struct queue_pages qp =3D { .pagelist =3D pagelist, .flags =3D flags, .nmask =3D nodes, - .prev =3D NULL, + .start =3D start, + .first =3D NULL, + .last =3D NULL, }; =20 - return walk_page_range(mm, start, end, &queue_pages_walk_ops, &qp); + err =3D walk_page_range(mm, start, end, &queue_pages_walk_ops, &qp); + + if (err !=3D -EFAULT) { + if (!qp.first) + /* whole range in hole */ + err =3D -EFAULT; + else if (!(flags & MPOL_MF_DISCONTIG_OK) && + (qp.last->vm_end < end)) + /* hole at tail side of range */ + err =3D -EFAULT; + } + + return err; } =20 /* @@ -738,8 +759,7 @@ static int mbind_range(struct mm_struct *mm, unsigned= long start, unsigned long vmend; =20 vma =3D find_vma(mm, start); - if (!vma || vma->vm_start > start) - return -EFAULT; + VM_BUG_ON(!vma); =20 prev =3D vma->vm_prev; if (start > vma->vm_start) --=20 1.8.3.1