Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp1837987iob; Fri, 29 Apr 2022 14:09:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz+Op7nqY5pbepskHfQPkL+IrQCCQraERil4VBXIFa/odr6PIGstaEY1hY5NfJjcizrt54E X-Received: by 2002:a65:5b81:0:b0:3aa:1671:c6a7 with SMTP id i1-20020a655b81000000b003aa1671c6a7mr906872pgr.169.1651266594391; Fri, 29 Apr 2022 14:09:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651266594; cv=none; d=google.com; s=arc-20160816; b=UKKg4sS2F/26n4BVOq3kVyjzs978PcAeMAZtB4rSck/EEAHvCgCLdLGyv0Nbg52S02 ZOtoDWTWaMGVB7O2NMNX+4BN5QA9mh7LBOR+9YNDEx/5jJZW8kSbkQqbihyyQtJ5qloz hb6So1/vjCO2S+2NZRulACWZ4MGwM5HtifNlhX8YNKB9h6eDTCsA2+QUrhWPYXNkqs4A n0N5g9fgo9+nli36AxSqjhezUrsYuMYSp2Svc27M8RyVLtHeraz9ZVTdDEXTuh1Y9KUf +EwSlShScoDWg3yJWiSfu1shn7LhscyAxnjN401qv6SzkxbBPbt+dCaGBCGZG1aYM3p9 VhaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Mw1vEF57DF/DSHOfcvK2jK3+BJnA4MIc7Hv6vQlLEvE=; b=QCPsmcE7M2eNvQnSmMBJpDsZOiZDGWBEMyynORvKOlhnOnet+hwt3tUsb8uKcmywRj oKBgKvAHmE3xLJ6zSbgiXAR3DYrnoYuK+QTZbkYmX10NqlMLIR89ShECqqMUcfvAo9nt 5VbdLPht9V/dqBi9B15+XU8WgiL++RcXGQXaqWvwKYlYOTILgUT5kiX2sZzBDqxog0Ix qAefSDulrranvplF957adhmEkfjJeByUh6zY2GCJsMkpwtA79R0JvT7YdiMA2IX6VaLg ZkxyQGhMkzGMTksa/JV6J90EE7pkM2KQ3HZ8Sixa0stJh8MoZxAeCZNutObbHkt5GzZU qMrQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="cYb99I/d"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z9-20020a630a49000000b003ab01be4e34si7849013pgk.678.2022.04.29.14.09.37; Fri, 29 Apr 2022 14:09:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="cYb99I/d"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1358096AbiD2KuF (ORCPT + 99 others); Fri, 29 Apr 2022 06:50:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59640 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1358212AbiD2Ks5 (ORCPT ); Fri, 29 Apr 2022 06:48:57 -0400 Received: from sin.source.kernel.org (sin.source.kernel.org [IPv6:2604:1380:40e1:4800::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6B83BC8BCA; Fri, 29 Apr 2022 03:44:10 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 87F23CE31AD; Fri, 29 Apr 2022 10:44:08 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A1FDC385A4; Fri, 29 Apr 2022 10:44:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1651229046; bh=xdLcGSFgeD/hce6ftZaN2X8YgTAMN42pVZmyF6hUKzo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cYb99I/dE7ZSC1s3k6qlrodmPe1S9xmMa2twkB2iKwAe3vkrCQNp45v1aZP6Vadv+ tGH3uU0bfROxK9Ig7Qp1v10OEvfLM27G49MUu3Tp+tv7yKfXvg8OCrhR5sNT+cr79t TOGwCIrhzClPs2uobaLnsrKwGQjT8PvCf9QcHX/M= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Greg Kroah-Hartman , David Hildenbrand , Linus Torvalds , Anand Jain , Andreas Gruenbacher Subject: [PATCH 5.15 32/33] mm: gup: make fault_in_safe_writeable() use fixup_user_fault() Date: Fri, 29 Apr 2022 12:42:19 +0200 Message-Id: <20220429104053.267876141@linuxfoundation.org> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220429104052.345760505@linuxfoundation.org> References: <20220429104052.345760505@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Linus Torvalds commit fe673d3f5bf1fc50cdc4b754831db91a2ec10126 upstream Instead of using GUP, make fault_in_safe_writeable() actually force a 'handle_mm_fault()' using the same fixup_user_fault() machinery that futexes already use. Using the GUP machinery meant that fault_in_safe_writeable() did not do everything that a real fault would do, ranging from not auto-expanding the stack segment, to not updating accessed or dirty flags in the page tables (GUP sets those flags on the pages themselves). The latter causes problems on architectures (like s390) that do accessed bit handling in software, which meant that fault_in_safe_writeable() didn't actually do all the fault handling it needed to, and trying to access the user address afterwards would still cause faults. Reported-and-tested-by: Andreas Gruenbacher Fixes: cdd591fc86e3 ("iov_iter: Introduce fault_in_iov_iter_writeable") Link: https://lore.kernel.org/all/CAHc6FU5nP+nziNGG0JAF1FUx-GV7kKFvM7aZuU_XD2_1v4vnvg@mail.gmail.com/ Acked-by: David Hildenbrand Signed-off-by: Linus Torvalds Signed-off-by: Anand Jain Signed-off-by: Greg Kroah-Hartman --- mm/gup.c | 57 +++++++++++++++++++-------------------------------------- 1 file changed, 19 insertions(+), 38 deletions(-) --- a/mm/gup.c +++ b/mm/gup.c @@ -1723,11 +1723,11 @@ EXPORT_SYMBOL(fault_in_writeable); * @uaddr: start of address range * @size: length of address range * - * Faults in an address range using get_user_pages, i.e., without triggering - * hardware page faults. This is primarily useful when we already know that - * some or all of the pages in the address range aren't in memory. + * Faults in an address range for writing. This is primarily useful when we + * already know that some or all of the pages in the address range aren't in + * memory. * - * Other than fault_in_writeable(), this function is non-destructive. + * Unlike fault_in_writeable(), this function is non-destructive. * * Note that we don't pin or otherwise hold the pages referenced that we fault * in. There's no guarantee that they'll stay in memory for any duration of @@ -1738,46 +1738,27 @@ EXPORT_SYMBOL(fault_in_writeable); */ size_t fault_in_safe_writeable(const char __user *uaddr, size_t size) { - unsigned long start = (unsigned long)untagged_addr(uaddr); - unsigned long end, nstart, nend; + unsigned long start = (unsigned long)uaddr, end; struct mm_struct *mm = current->mm; - struct vm_area_struct *vma = NULL; - int locked = 0; + bool unlocked = false; - nstart = start & PAGE_MASK; + if (unlikely(size == 0)) + return 0; end = PAGE_ALIGN(start + size); - if (end < nstart) + if (end < start) end = 0; - for (; nstart != end; nstart = nend) { - unsigned long nr_pages; - long ret; - if (!locked) { - locked = 1; - mmap_read_lock(mm); - vma = find_vma(mm, nstart); - } else if (nstart >= vma->vm_end) - vma = vma->vm_next; - if (!vma || vma->vm_start >= end) - break; - nend = end ? min(end, vma->vm_end) : vma->vm_end; - if (vma->vm_flags & (VM_IO | VM_PFNMAP)) - continue; - if (nstart < vma->vm_start) - nstart = vma->vm_start; - nr_pages = (nend - nstart) / PAGE_SIZE; - ret = __get_user_pages_locked(mm, nstart, nr_pages, - NULL, NULL, &locked, - FOLL_TOUCH | FOLL_WRITE); - if (ret <= 0) + mmap_read_lock(mm); + do { + if (fixup_user_fault(mm, start, FAULT_FLAG_WRITE, &unlocked)) break; - nend = nstart + ret * PAGE_SIZE; - } - if (locked) - mmap_read_unlock(mm); - if (nstart == end) - return 0; - return size - min_t(size_t, nstart - start, size); + start = (start + PAGE_SIZE) & PAGE_MASK; + } while (start != end); + mmap_read_unlock(mm); + + if (size > (unsigned long)uaddr - start) + return size - ((unsigned long)uaddr - start); + return 0; } EXPORT_SYMBOL(fault_in_safe_writeable);