From patchwork Fri Jul 2 22:57:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 12356775 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=-26.4 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT,USER_IN_DEF_DKIM_WL 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 51C8EC07E95 for ; Fri, 2 Jul 2021 22:57:19 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id DA4BC60BD3 for ; Fri, 2 Jul 2021 22:57:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DA4BC60BD3 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 79ABF6B0085; Fri, 2 Jul 2021 18:57:18 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 74ADB8D0007; Fri, 2 Jul 2021 18:57:18 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5C48B8D0005; Fri, 2 Jul 2021 18:57:18 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0214.hostedemail.com [216.40.44.214]) by kanga.kvack.org (Postfix) with ESMTP id 3C0136B0085 for ; Fri, 2 Jul 2021 18:57:18 -0400 (EDT) Received: from smtpin35.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id DE0A3181BA3E1 for ; Fri, 2 Jul 2021 22:57:17 +0000 (UTC) X-FDA: 78319160514.35.AB5E542 Received: from mail-qv1-f74.google.com (mail-qv1-f74.google.com [209.85.219.74]) by imf30.hostedemail.com (Postfix) with ESMTP id 959CDE001986 for ; Fri, 2 Jul 2021 22:57:17 +0000 (UTC) Received: by mail-qv1-f74.google.com with SMTP id h7-20020a0ceda70000b02902af042354f1so1340438qvr.9 for ; Fri, 02 Jul 2021 15:57:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=eD/aaF0+/ogeXZeNjhDOEniG4W67mBj100J0eAxvQ+U=; b=lGixFLToeD1HCgLYbj4zld5OKHRt6Gj/QGs1cGV1l7z2nVvMnIApVsC9qcAN1YXOC6 y+G0luXpsadhVbnumJ9zn+n30sMmF5eRkxdgk+NdMZ4flxdzPj0TFBoc1vlQfX8euPLR GphDdbYtHfsc6HSLjooOXKGJTwKR2yQ507LS+sLu+1H352oARcmwRukhizurj28zW8Xt LeGMfjTbcmeh0GsdKD3bYdMFU3FtQJs4Nl2BaR6LzQxgqmKk86NSmmG7As0YqN5l1j0D LECZgY4lBw7bRZvj5GG5t60ZvMqmRdtznuAhraS28IDlFNvqQn8c4HexnPm0ylIN65yR 3k1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=eD/aaF0+/ogeXZeNjhDOEniG4W67mBj100J0eAxvQ+U=; b=okyENL7acZ7RGmc9HzO+hYjBz7fSF3+2mMobxaGxbwhvhKyvjRS989/ULaXQvAHme4 vtoOKWJO7isoQBQjCg+1TkP1hmNr1TNw7u3A1UNoRXwDzZC+94xzrnRWhAUXfMV2Ad1h 21ajGgq0ehasBe6t7Sl9aTdXgKb94otLmxewYECDfuaS2gzLKMEmF69cWD3kRKe72bAK aKGNeLa/fFC9AP0OKuGemKOwbas6sXuqb5bhCTxQvN06TkyArwzlES7LgA9GndBEUROU koUfIZZQLw5/hPHCOQTji0MVzH/jkMy6teyKgbMsJc3+pjSO0r0OJ8Jq6y+SYw0b2xSC 8w5w== X-Gm-Message-State: AOAM532Hj93injlfH3eb3vnnItgOg9K0PbadVBTtxR9mUZuZA/DWsoAE 17YjztaqfzxYHiA/hTul0v791lU= X-Google-Smtp-Source: ABdhPJwqb2avj7yI+m+Fn5WehCafNibnnB9vG8LmiHheaxe5O83a4qAJ7H3M/RW7cRnyoFEp8B5LMXo= X-Received: from pcc-desktop.svl.corp.google.com ([2620:15c:2ce:200:7c5b:5407:a2db:c8fb]) (user=pcc job=sendgmr) by 2002:ad4:50c5:: with SMTP id e5mr1779283qvq.40.1625266636905; Fri, 02 Jul 2021 15:57:16 -0700 (PDT) Date: Fri, 2 Jul 2021 15:57:04 -0700 In-Reply-To: <20210702225705.2477947-1-pcc@google.com> Message-Id: <20210702225705.2477947-2-pcc@google.com> Mime-Version: 1.0 References: <20210702225705.2477947-1-pcc@google.com> X-Mailer: git-send-email 2.32.0.93.g670b81a890-goog Subject: [PATCH v3 1/2] userfaultfd: do not untag user pointers From: Peter Collingbourne To: Catalin Marinas , Vincenzo Frascino , Dave Martin , Will Deacon , Andrew Morton , Andrea Arcangeli Cc: Peter Collingbourne , Alistair Delva , Lokesh Gidra , William McVicker , Evgenii Stepanov , Mitch Phillips , Linux ARM , linux-mm@kvack.org, Andrey Konovalov , stable@vger.kernel.org Authentication-Results: imf30.hostedemail.com; dkim=pass header.d=google.com header.s=20161025 header.b=lGixFLTo; spf=pass (imf30.hostedemail.com: domain of 3zJnfYAMKCIs4rrv33v0t.r310x29C-11zAprz.36v@flex--pcc.bounces.google.com designates 209.85.219.74 as permitted sender) smtp.mailfrom=3zJnfYAMKCIs4rrv33v0t.r310x29C-11zAprz.36v@flex--pcc.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com X-Stat-Signature: h9qx7t9yrb7zi976nm1oq3mxuj5k3g7s X-Rspamd-Queue-Id: 959CDE001986 X-Rspamd-Server: rspam06 X-HE-Tag: 1625266637-264900 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: 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. 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"). [1] https://source.android.com/devices/tech/debug/tagged-pointers [2] tools/testing/selftests/vm/userfaultfd.c Signed-off-by: Peter Collingbourne Link: https://linux-review.googlesource.com/id/I761aa9f0344454c482b83fcfcce547db0a25501b Fixes: 63f0c6037965 ("arm64: Introduce prctl() options to control the tagged user addresses ABI") Cc: # 5.4 Reported-by: kernel test robot Reported-by: kernel test robot Reported-by: kernel test robot Reported-by: kernel test robot Reviewed-by: Andrey Konovalov --- Documentation/arm64/tagged-address-abi.rst | 25 +++++++++++++++------- fs/userfaultfd.c | 22 +++++++++---------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst index 459e6b66ff68..737f9d8565a2 100644 --- a/Documentation/arm64/tagged-address-abi.rst +++ b/Documentation/arm64/tagged-address-abi.rst @@ -45,14 +45,23 @@ how the user addresses are used by the kernel: 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`` argument to the ``UFFDIO_REGISTER`` ``ioctl()`` + 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 diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index dd7a6c62b56f..7613efe002c1 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1236,23 +1236,21 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx, } 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; } @@ -1313,7 +1311,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, vm_flags |= VM_UFFD_MINOR; } - ret = validate_range(mm, &uffdio_register.range.start, + ret = validate_range(mm, uffdio_register.range.start, uffdio_register.range.len); if (ret) goto out; @@ -1519,7 +1517,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx, 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; @@ -1668,7 +1666,7 @@ static int userfaultfd_wake(struct userfaultfd_ctx *ctx, 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; @@ -1708,7 +1706,7 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx, 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; /* @@ -1765,7 +1763,7 @@ static int userfaultfd_zeropage(struct userfaultfd_ctx *ctx, 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;