Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp3680736pxv; Mon, 26 Jul 2021 09:15:58 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxmkhWPBirGS/Y+m8DKVKU3NnscndDKrO6Dcn7ZrMnPwV+3yBxZRsUh0/bdlSk9AmqawyQA X-Received: by 2002:a50:e78c:: with SMTP id b12mr16352586edn.306.1627316158028; Mon, 26 Jul 2021 09:15:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627316158; cv=none; d=google.com; s=arc-20160816; b=MbnrNU7H1nZItvlPi4G/gO/c2jDVNwHoY733YxAPipXu5C9R3/ssSmvyhYp0mdMuUK xMEKYUr5sImy2HB7vvGUyi7HdEnLmS7wj5SuI57h7veAXWlkInkQd2kouk/ajuoRDk9I /IIBaXmnpXWMzjhaANfSxvzdZPVWwPAoloFY9l22cTUMS8TBz1zKHlJgVWR4AfH4lrR6 xUa52grSe/XGaxgHqB0sgG5xybtI2X/MKJDedlAX9YqBwbAyBg+KvVpg1FOR4z2de6N/ 4XV/ESrdUMqr+mvn7nN5DOII2bZNDsVRKM5JwE7+fB1sMDA8N8GEjmG1V1IKuD/XWIGY 6o+A== 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=D3h9C4hs5RpEQoLgbBZqqwWlfc8fUeeyjv2YtjbeQpU=; b=dJdTduH4bRDW9Yw8Ni0KxKbLeGKiHNMCat7fIscDbvmPgedXyP2TKo/EhqQTB+G3X3 lCwhZ+lcM/xDBk/Xyz/eD2rsUsNs3AZ9h4s0HPDswmLESwSlQ4/80vt4auJwjKWMR35j J0r+VsVxBZkusj4+/Qa3cwnleehWoUKdk/FrItm2e3WEndC5jzotBZheF6rcbvt9F6ma FOGo8CmxRuiwCIn1xwH7lWHCoz0Itp53LHHbP3vAKVnFOW1bpR9NOCAuHWN0p3uw/FNo 1Lq4YG9Yw92CyWFUCcP5NtpjH8i2ADvQEhkes0J+KRkS+e7s/p9U8alspjD8KeXVrm2o 8Gzg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=S4+oOVpp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 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 vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t15si241856ejd.275.2021.07.26.09.15.35; Mon, 26 Jul 2021 09:15:58 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=S4+oOVpp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 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 S234253AbhGZPdT (ORCPT + 99 others); Mon, 26 Jul 2021 11:33:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:59642 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236404AbhGZPSs (ORCPT ); Mon, 26 Jul 2021 11:18:48 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 5EF7160FC2; Mon, 26 Jul 2021 15:59:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1627315156; bh=qj1s6WAPiwYljmjanr4iEukXgVMG+2Tt9T6QjPUJxLM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S4+oOVpp+OD0wLeD/9NTCmsNwK4djQ23YVnSzX0sXY2UaowVG1xyLZLggSLQCcX7c 6qRchkfF2L7eePgzgv8Y0VRiN8gIbYTClErUxATKytKSkknfKb+wfZNdM4vNrOWvyi C5C/XgtO2U3Ow6mmXVaBWqwI2TMWX8xcEVmGpdog= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Peter Collingbourne , Andrey Konovalov , Catalin Marinas , Alistair Delva , Andrea Arcangeli , Dave Martin , Evgenii Stepanov , Lokesh Gidra , Mitch Phillips , Vincenzo Frascino , Will Deacon , William McVicker , Andrew Morton , Linus Torvalds Subject: [PATCH 5.4 095/108] userfaultfd: do not untag user pointers Date: Mon, 26 Jul 2021 17:39:36 +0200 Message-Id: <20210726153834.730063469@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210726153831.696295003@linuxfoundation.org> References: <20210726153831.696295003@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Peter Collingbourne commit e71e2ace5721a8b921dca18b045069e7bb411277 upstream. Patch series "userfaultfd: do not untag user pointers", v5. If a user program uses userfaultfd on ranges of heap memory, it may end up passing a tagged pointer to the kernel in the range.start field of the UFFDIO_REGISTER ioctl. This can happen when using an MTE-capable allocator, or on Android if using the Tagged Pointers feature for MTE readiness [1]. When a fault subsequently occurs, the tag is stripped from the fault address returned to the application in the fault.address field of struct uffd_msg. However, from the application's perspective, the tagged address *is* the memory address, so if the application is unaware of memory tags, it may get confused by receiving an address that is, from its point of view, outside of the bounds of the allocation. We observed this behavior in the kselftest for userfaultfd [2] but other applications could have the same problem. Address this by not untagging pointers passed to the userfaultfd ioctls. Instead, let the system call fail. Also change the kselftest to use mmap so that it doesn't encounter this problem. [1] https://source.android.com/devices/tech/debug/tagged-pointers [2] tools/testing/selftests/vm/userfaultfd.c This patch (of 2): Do not untag pointers passed to the userfaultfd ioctls. Instead, let the system call fail. This will provide an early indication of problems with tag-unaware userspace code instead of letting the code get confused later, and is consistent with how we decided to handle brk/mmap/mremap in commit dcde237319e6 ("mm: Avoid creating virtual address aliases in brk()/mmap()/mremap()"), as well as being consistent with the existing tagged address ABI documentation relating to how ioctl arguments are handled. The code change is a revert of commit 7d0325749a6c ("userfaultfd: untag user pointers") plus some fixups to some additional calls to validate_range that have appeared since then. [1] https://source.android.com/devices/tech/debug/tagged-pointers [2] tools/testing/selftests/vm/userfaultfd.c Link: https://lkml.kernel.org/r/20210714195437.118982-1-pcc@google.com Link: https://lkml.kernel.org/r/20210714195437.118982-2-pcc@google.com Link: https://linux-review.googlesource.com/id/I761aa9f0344454c482b83fcfcce547db0a25501b Fixes: 63f0c6037965 ("arm64: Introduce prctl() options to control the tagged user addresses ABI") Signed-off-by: Peter Collingbourne Reviewed-by: Andrey Konovalov Reviewed-by: Catalin Marinas Cc: Alistair Delva Cc: Andrea Arcangeli Cc: Dave Martin Cc: Evgenii Stepanov Cc: Lokesh Gidra Cc: Mitch Phillips Cc: Vincenzo Frascino Cc: Will Deacon Cc: William McVicker Cc: [5.4] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- Documentation/arm64/tagged-address-abi.rst | 26 ++++++++++++++++++-------- fs/userfaultfd.c | 22 ++++++++++------------ 2 files changed, 28 insertions(+), 20 deletions(-) --- a/Documentation/arm64/tagged-address-abi.rst +++ b/Documentation/arm64/tagged-address-abi.rst @@ -45,14 +45,24 @@ how the user addresses are used by the k 1. User addresses not accessed by the kernel but used for address space management (e.g. ``mprotect()``, ``madvise()``). The use of valid - tagged pointers in this context is allowed with the exception of - ``brk()``, ``mmap()`` and the ``new_address`` argument to - ``mremap()`` as these have the potential to alias with existing - user addresses. - - NOTE: This behaviour changed in v5.6 and so some earlier kernels may - incorrectly accept valid tagged pointers for the ``brk()``, - ``mmap()`` and ``mremap()`` system calls. + tagged pointers in this context is allowed with these exceptions: + + - ``brk()``, ``mmap()`` and the ``new_address`` argument to + ``mremap()`` as these have the potential to alias with existing + user addresses. + + NOTE: This behaviour changed in v5.6 and so some earlier kernels may + incorrectly accept valid tagged pointers for the ``brk()``, + ``mmap()`` and ``mremap()`` system calls. + + - The ``range.start``, ``start`` and ``dst`` arguments to the + ``UFFDIO_*`` ``ioctl()``s used on a file descriptor obtained from + ``userfaultfd()``, as fault addresses subsequently obtained by reading + the file descriptor will be untagged, which may otherwise confuse + tag-unaware programs. + + NOTE: This behaviour changed in v5.14 and so some earlier kernels may + incorrectly accept valid tagged pointers for this system call. 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI relaxation is disabled by default and the application thread needs to --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1272,23 +1272,21 @@ static __always_inline void wake_userfau } static __always_inline int validate_range(struct mm_struct *mm, - __u64 *start, __u64 len) + __u64 start, __u64 len) { __u64 task_size = mm->task_size; - *start = untagged_addr(*start); - - if (*start & ~PAGE_MASK) + if (start & ~PAGE_MASK) return -EINVAL; if (len & ~PAGE_MASK) return -EINVAL; if (!len) return -EINVAL; - if (*start < mmap_min_addr) + if (start < mmap_min_addr) return -EINVAL; - if (*start >= task_size) + if (start >= task_size) return -EINVAL; - if (len > task_size - *start) + if (len > task_size - start) return -EINVAL; return 0; } @@ -1338,7 +1336,7 @@ static int userfaultfd_register(struct u goto out; } - ret = validate_range(mm, &uffdio_register.range.start, + ret = validate_range(mm, uffdio_register.range.start, uffdio_register.range.len); if (ret) goto out; @@ -1527,7 +1525,7 @@ static int userfaultfd_unregister(struct if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister))) goto out; - ret = validate_range(mm, &uffdio_unregister.start, + ret = validate_range(mm, uffdio_unregister.start, uffdio_unregister.len); if (ret) goto out; @@ -1678,7 +1676,7 @@ static int userfaultfd_wake(struct userf if (copy_from_user(&uffdio_wake, buf, sizeof(uffdio_wake))) goto out; - ret = validate_range(ctx->mm, &uffdio_wake.start, uffdio_wake.len); + ret = validate_range(ctx->mm, uffdio_wake.start, uffdio_wake.len); if (ret) goto out; @@ -1718,7 +1716,7 @@ static int userfaultfd_copy(struct userf sizeof(uffdio_copy)-sizeof(__s64))) goto out; - ret = validate_range(ctx->mm, &uffdio_copy.dst, uffdio_copy.len); + ret = validate_range(ctx->mm, uffdio_copy.dst, uffdio_copy.len); if (ret) goto out; /* @@ -1774,7 +1772,7 @@ static int userfaultfd_zeropage(struct u sizeof(uffdio_zeropage)-sizeof(__s64))) goto out; - ret = validate_range(ctx->mm, &uffdio_zeropage.range.start, + ret = validate_range(ctx->mm, uffdio_zeropage.range.start, uffdio_zeropage.range.len); if (ret) goto out;