From patchwork Mon Nov 4 06:40:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Li Xinhai X-Patchwork-Id: 11225007 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D491F13A4 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 88A6B222CD 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 88A6B222CD 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) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 9ECDD6B0006; Mon, 4 Nov 2019 01:42:22 -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 903286B0007; Mon, 4 Nov 2019 01:42:22 -0500 (EST) X-Original-To: linux-mm@kvack.org 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-Spam-Summary: 30,2,0,7d148ccb24719402,d41d8cd98f00b204,lixinhai_lxh@126.com,::lixinhai.lxh@gmail.com: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:lixinhai.li@gmail.com,RULES_HIT:41:69:355:379:541:582:800:960:973:988:989:1152:1260:1311:1314:1345:1431:1437:1515:1535:1544:1605:1711:1730:1747:1777:1792:1801:2198:2199:2393:2559:2562:3138:3139:3140:3141:3142:3865:3866:3867:3868:3870:3871:3872:3874:4117:4250:4605:5007:6121:6653:6755:7514:7576:7875:7903:8634:8660:9121:9592:10004:11026:11232:11233:11334:11473:11658:11914:12043:12050:12219:12291:12295:12296:12297:12438:12555:12679:12683:12895:13141:13148:13180:13229:13230:13870:13894:14096:14181:14394:14721:21060:21080:21094:21323:21324:21451:21627:21740:21889:21939:30054:30070:30074,0,RBL:220.181.15.113:@126.com:.lbl8.mailshell.net-62.50.2.100 66.100.201.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF 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 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 applied 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() for 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() for 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_range()") Fixes: 48684a65b4e3 ("mm: pagewalk: fix misbehavior of walk_page_range for 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; }; /* @@ -618,6 +620,21 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end, unsigned long endvma = vma->vm_end; unsigned long flags = qp->flags; + /* range check first */ + VM_BUG_ON((vma->vm_start > start) || (vma->vm_end < end)); + + if (!qp->first) { + qp->first = 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 = 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, if (endvma > end) endvma = end; - if (vma->vm_start > start) - start = 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 = vma; 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 start, unsigned long end, nodemask_t *nodes, unsigned long flags, struct list_head *pagelist) { + int err; struct queue_pages qp = { .pagelist = pagelist, .flags = flags, .nmask = nodes, - .prev = NULL, + .start = start, + .first = NULL, + .last = NULL, }; - return walk_page_range(mm, start, end, &queue_pages_walk_ops, &qp); + err = walk_page_range(mm, start, end, &queue_pages_walk_ops, &qp); + + if (err != -EFAULT) { + if (!qp.first) + /* whole range in hole */ + err = -EFAULT; + else if (!(flags & MPOL_MF_DISCONTIG_OK) && + (qp.last->vm_end < end)) + /* hole at tail side of range */ + err = -EFAULT; + } + + return err; } /* @@ -738,8 +759,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, unsigned long vmend; vma = find_vma(mm, start); - if (!vma || vma->vm_start > start) - return -EFAULT; + VM_BUG_ON(!vma); prev = vma->vm_prev; if (start > vma->vm_start)