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=-18.6 required=3.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=unavailable 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 3CE43C10F00 for ; Mon, 18 Mar 2019 17:17:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F288F217D8 for ; Mon, 18 Mar 2019 17:17:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="r7BuUjT8" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727697AbfCRRRv (ORCPT ); Mon, 18 Mar 2019 13:17:51 -0400 Received: from mail-qt1-f202.google.com ([209.85.160.202]:41301 "EHLO mail-qt1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726987AbfCRRRu (ORCPT ); Mon, 18 Mar 2019 13:17:50 -0400 Received: by mail-qt1-f202.google.com with SMTP id d49so4349404qtk.8 for ; Mon, 18 Mar 2019 10:17:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=hkZRyLCyEaEj0h1/8UX44FTe5HP+CD8YXp42TcJT5X4=; b=r7BuUjT872vqMsVH/wkX0rjSoIhlckZYzTG8nkCBzc21HrrSP19mTaFG7c/ZUIfgAD lzqbtolzZhCEXgEjV5Dc9Xqs/UljOaAvtRhFVaA0zAgNWOvDVrOZTK86tNsjly501M+i AYUz5hIxJkGAK0BJCTA9Td2ckq1vEAjsrtDJj2d9NzWPTchq1PPgOx/JRG7fniXo3qP0 xXd+E9EBHtRgO2gNveThVNHJyyTj8PAxfe+1vn5XX4QV2ryXVMc7CcdeCwHwF1bZ7hSF 6ayQgkhu3GgiLEigUaW9xs5aq5tzxIZ+FvU/WGxFOfLlXMKdaCJOzaCW9E06Em0uNsw4 0W3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=hkZRyLCyEaEj0h1/8UX44FTe5HP+CD8YXp42TcJT5X4=; b=OGdC5qP5DaXm1EGvBtwNMnaim+RnGqAm+hq7OQ3GtLVIhKQpZtLOJBVC74zOzAXZgl lM+k+xNkqX2AmGYzpbta7NYbp5g8M9ol5ql4X94IwIAkU42+mGcGpRsF4+9J+d1EP9Cz wpitjToWws8gu1aNnuBI0vQpENTjQbH0W7lHuMj3+WmbFmJql702lVntS0JK7M9H8kuK OU0SCoZXrHpUC/7xlUTdP7BtP8pFDlT6UuOC0QmuKbKUXfbwZdAbCkGrV5cVfIvQzPzB Tmwwr0NVzdnm3JxI8xxvMx2WR4w2LC+XEcspYktwTYDU8DVWMwahH89WKb+JKmsZrjC/ mEqA== X-Gm-Message-State: APjAAAWRgYTuG1fGTKLvcpeUk+B+xhFfLUUjLWSoe+kt28BefMsYTqE9 NvgmkLolDX2p6cM4eaZGdWLX9az09RC5l1aJ X-Google-Smtp-Source: APXvYqzkeAXzAy3oNYG2BR4miR/Z8Fu9oC+SjuURt/xYQhyeLrh/e+rUUiZ2TAsT5ZCM3sbUSVpsZp73cydX3AZ1 X-Received: by 2002:ac8:21f2:: with SMTP id 47mr10992908qtz.9.1552929468913; Mon, 18 Mar 2019 10:17:48 -0700 (PDT) Date: Mon, 18 Mar 2019 18:17:32 +0100 Message-Id: Mime-Version: 1.0 X-Mailer: git-send-email 2.21.0.225.g810b269d1ac-goog Subject: [PATCH v12 00/13] arm64: untag user pointers passed to the kernel From: Andrey Konovalov To: Catalin Marinas , Will Deacon , Mark Rutland , Robin Murphy , Kees Cook , Kate Stewart , Greg Kroah-Hartman , Andrew Morton , Ingo Molnar , "Kirill A . Shutemov" , Shuah Khan , Vincenzo Frascino , Eric Dumazet , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , Steven Rostedt , Ingo Molnar , Peter Zijlstra , Arnaldo Carvalho de Melo , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Dmitry Vyukov , Kostya Serebryany , Evgeniy Stepanov , Lee Smith , Ramana Radhakrishnan , Jacob Bramley , Ruben Ayrapetyan , Chintan Pandya , Luc Van Oostenryck , Dave Martin , Kevin Brodsky , Szabolcs Nagy , Andrey Konovalov Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org === Overview arm64 has a feature called Top Byte Ignore, which allows to embed pointer tags into the top byte of each pointer. Userspace programs (such as HWASan, a memory debugging tool [1]) might use this feature and pass tagged user pointers to the kernel through syscalls or other interfaces. Right now the kernel is already able to handle user faults with tagged pointers, due to these patches: 1. 81cddd65 ("arm64: traps: fix userspace cache maintenance emulation on a tagged pointer") 2. 7dcd9dd8 ("arm64: hw_breakpoint: fix watchpoint matching for tagged pointers") 3. 276e9327 ("arm64: entry: improve data abort handling of tagged pointers") This patchset extends tagged pointer support to syscall arguments. As per the proposed ABI change [3], tagged pointers are only allowed to be passed to syscalls when they point to memory ranges obtained by anonymous mmap() or sbrk() (see the patchset [3] for more details). For non-memory syscalls this is done by untaging user pointers when the kernel performs pointer checking to find out whether the pointer comes from userspace (most notably in access_ok). The untagging is done only when the pointer is being checked, the tag is preserved as the pointer makes its way through the kernel and stays tagged when the kernel dereferences the pointer when perfoming user memory accesses. Memory syscalls (mmap, mprotect, etc.) don't do user memory accesses but rather deal with memory ranges, and untagged pointers are better suited to describe memory ranges internally. Thus for memory syscalls we untag pointers completely when they enter the kernel. === Other approaches One of the alternative approaches to untagging that was considered is to completely strip the pointer tag as the pointer enters the kernel with some kind of a syscall wrapper, but that won't work with the countless number of different ioctl calls. With this approach we would need a custom wrapper for each ioctl variation, which doesn't seem practical. An alternative approach to untagging pointers in memory syscalls prologues is to inspead allow tagged pointers to be passed to find_vma() (and other vma related functions) and untag them there. Unfortunately, a lot of find_vma() callers then compare or subtract the returned vma start and end fields against the pointer that was being searched. Thus this approach would still require changing all find_vma() callers. === Testing The following testing approaches has been taken to find potential issues with user pointer untagging: 1. Static testing (with sparse [2] and separately with a custom static analyzer based on Clang) to track casts of __user pointers to integer types to find places where untagging needs to be done. 2. Static testing with grep to find parts of the kernel that call find_vma() (and other similar functions) or directly compare against vm_start/vm_end fields of vma. 3. Static testing with grep to find parts of the kernel that compare user pointers with TASK_SIZE or other similar consts and macros. 4. Dynamic testing: adding BUG_ON(has_tag(addr)) to find_vma() and running a modified syzkaller version that passes tagged pointers to the kernel. Based on the results of the testing the requried patches have been added to the patchset. === Notes This patchset is meant to be merged together with "arm64 relaxed ABI" [3]. This patchset is a prerequisite for ARM's memory tagging hardware feature support [4]. This patchset has been merged into the Pixel 2 kernel tree and is now being used to enable testing of Pixel 2 phones with HWASan. Thanks! [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html [2] https://github.com/lucvoo/sparse-dev/commit/5f960cb10f56ec2017c128ef9d16060e0145f292 [3] https://lkml.org/lkml/2019/3/18/819 [4] https://community.arm.com/processors/b/blog/posts/arm-a-profile-architecture-2018-developments-armv85a Changes in v12: - Changed untagging in tcp_zerocopy_receive() to also untag zc->address. - Fixed untagging in prctl_set_mm* to only untag pointers for vma lookups and validity checks, but leave them as is for actual user space accesses. - Updated the link to the v2 of the "arm64 relaxed ABI" patchset [3]. - Dropped the documentation patch, as the "arm64 relaxed ABI" patchset [3] handles that. Changes in v11: - Added "uprobes, arm64: untag user pointers in find_active_uprobe" patch. - Added "bpf, arm64: untag user pointers in stack_map_get_build_id_offset" patch. - Fixed "tracing, arm64: untag user pointers in seq_print_user_ip" to correctly perform subtration with a tagged addr. - Moved untagged_addr() from SYSCALL_DEFINE3(mprotect) and SYSCALL_DEFINE4(pkey_mprotect) to do_mprotect_pkey(). - Moved untagged_addr() definition for other arches from include/linux/memory.h to include/linux/mm.h. - Changed untagging in strn*_user() to perform userspace accesses through tagged pointers. - Updated the documentation to mention that passing tagged pointers to memory syscalls is allowed. - Updated the test to use malloc'ed memory instead of stack memory. Changes in v10: - Added "mm, arm64: untag user pointers passed to memory syscalls" back. - New patch "fs, arm64: untag user pointers in fs/userfaultfd.c". - New patch "net, arm64: untag user pointers in tcp_zerocopy_receive". - New patch "kernel, arm64: untag user pointers in prctl_set_mm*". - New patch "tracing, arm64: untag user pointers in seq_print_user_ip". Changes in v9: - Rebased onto 4.20-rc6. - Used u64 instead of __u64 in type casts in the untagged_addr macro for arm64. - Added braces around (addr) in the untagged_addr macro for other arches. Changes in v8: - Rebased onto 65102238 (4.20-rc1). - Added a note to the cover letter on why syscall wrappers/shims that untag user pointers won't work. - Added a note to the cover letter that this patchset has been merged into the Pixel 2 kernel tree. - Documentation fixes, in particular added a list of syscalls that don't support tagged user pointers. Changes in v7: - Rebased onto 17b57b18 (4.19-rc6). - Dropped the "arm64: untag user address in __do_user_fault" patch, since the existing patches already handle user faults properly. - Dropped the "usb, arm64: untag user addresses in devio" patch, since the passed pointer must come from a vma and therefore be untagged. - Dropped the "arm64: annotate user pointers casts detected by sparse" patch (see the discussion to the replies of the v6 of this patchset). - Added more context to the cover letter. - Updated Documentation/arm64/tagged-pointers.txt. Changes in v6: - Added annotations for user pointer casts found by sparse. - Rebased onto 050cdc6c (4.19-rc1+). Changes in v5: - Added 3 new patches that add untagging to places found with static analysis. - Rebased onto 44c929e1 (4.18-rc8). Changes in v4: - Added a selftest for checking that passing tagged pointers to the kernel succeeds. - Rebased onto 81e97f013 (4.18-rc1+). Changes in v3: - Rebased onto e5c51f30 (4.17-rc6+). - Added linux-arch@ to the list of recipients. Changes in v2: - Rebased onto 2d618bdf (4.17-rc3+). - Removed excessive untagging in gup.c. - Removed untagging pointers returned from __uaccess_mask_ptr. Changes in v1: - Rebased onto 4.17-rc1. Changes in RFC v2: - Added "#ifndef untagged_addr..." fallback in linux/uaccess.h instead of defining it for each arch individually. - Updated Documentation/arm64/tagged-pointers.txt. - Dropped "mm, arm64: untag user addresses in memory syscalls". - Rebased onto 3eb2ce82 (4.16-rc7). Signed-off-by: Andrey Konovalov Andrey Konovalov (13): uaccess: add untagged_addr definition for other arches arm64: untag user pointers in access_ok and __uaccess_mask_ptr lib, arm64: untag user pointers in strn*_user mm, arm64: untag user pointers passed to memory syscalls mm, arm64: untag user pointers in mm/gup.c fs, arm64: untag user pointers in copy_mount_options fs, arm64: untag user pointers in fs/userfaultfd.c net, arm64: untag user pointers in tcp_zerocopy_receive kernel, arm64: untag user pointers in prctl_set_mm* tracing, arm64: untag user pointers in seq_print_user_ip uprobes, arm64: untag user pointers in find_active_uprobe bpf, arm64: untag user pointers in stack_map_get_build_id_offset selftests, arm64: add a selftest for passing tagged pointers to kernel arch/arm64/include/asm/uaccess.h | 10 +++-- fs/namespace.c | 2 +- fs/userfaultfd.c | 5 +++ include/linux/mm.h | 4 ++ ipc/shm.c | 2 + kernel/bpf/stackmap.c | 6 ++- kernel/events/uprobes.c | 2 + kernel/sys.c | 44 +++++++++++++------ kernel/trace/trace_output.c | 5 ++- lib/strncpy_from_user.c | 3 +- lib/strnlen_user.c | 3 +- mm/gup.c | 4 ++ mm/madvise.c | 2 + mm/mempolicy.c | 5 +++ mm/migrate.c | 1 + mm/mincore.c | 2 + mm/mlock.c | 5 +++ mm/mmap.c | 7 +++ mm/mprotect.c | 1 + mm/mremap.c | 2 + mm/msync.c | 2 + net/ipv4/tcp.c | 9 +++- tools/testing/selftests/arm64/.gitignore | 1 + tools/testing/selftests/arm64/Makefile | 11 +++++ .../testing/selftests/arm64/run_tags_test.sh | 12 +++++ tools/testing/selftests/arm64/tags_test.c | 21 +++++++++ 26 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 tools/testing/selftests/arm64/.gitignore create mode 100644 tools/testing/selftests/arm64/Makefile create mode 100755 tools/testing/selftests/arm64/run_tags_test.sh create mode 100644 tools/testing/selftests/arm64/tags_test.c -- 2.21.0.225.g810b269d1ac-goog From mboxrd@z Thu Jan 1 00:00:00 1970 From: andreyknvl at google.com (Andrey Konovalov) Date: Mon, 18 Mar 2019 18:17:32 +0100 Subject: [PATCH v12 00/13] arm64: untag user pointers passed to the kernel Message-ID: === Overview arm64 has a feature called Top Byte Ignore, which allows to embed pointer tags into the top byte of each pointer. Userspace programs (such as HWASan, a memory debugging tool [1]) might use this feature and pass tagged user pointers to the kernel through syscalls or other interfaces. Right now the kernel is already able to handle user faults with tagged pointers, due to these patches: 1. 81cddd65 ("arm64: traps: fix userspace cache maintenance emulation on a tagged pointer") 2. 7dcd9dd8 ("arm64: hw_breakpoint: fix watchpoint matching for tagged pointers") 3. 276e9327 ("arm64: entry: improve data abort handling of tagged pointers") This patchset extends tagged pointer support to syscall arguments. As per the proposed ABI change [3], tagged pointers are only allowed to be passed to syscalls when they point to memory ranges obtained by anonymous mmap() or sbrk() (see the patchset [3] for more details). For non-memory syscalls this is done by untaging user pointers when the kernel performs pointer checking to find out whether the pointer comes from userspace (most notably in access_ok). The untagging is done only when the pointer is being checked, the tag is preserved as the pointer makes its way through the kernel and stays tagged when the kernel dereferences the pointer when perfoming user memory accesses. Memory syscalls (mmap, mprotect, etc.) don't do user memory accesses but rather deal with memory ranges, and untagged pointers are better suited to describe memory ranges internally. Thus for memory syscalls we untag pointers completely when they enter the kernel. === Other approaches One of the alternative approaches to untagging that was considered is to completely strip the pointer tag as the pointer enters the kernel with some kind of a syscall wrapper, but that won't work with the countless number of different ioctl calls. With this approach we would need a custom wrapper for each ioctl variation, which doesn't seem practical. An alternative approach to untagging pointers in memory syscalls prologues is to inspead allow tagged pointers to be passed to find_vma() (and other vma related functions) and untag them there. Unfortunately, a lot of find_vma() callers then compare or subtract the returned vma start and end fields against the pointer that was being searched. Thus this approach would still require changing all find_vma() callers. === Testing The following testing approaches has been taken to find potential issues with user pointer untagging: 1. Static testing (with sparse [2] and separately with a custom static analyzer based on Clang) to track casts of __user pointers to integer types to find places where untagging needs to be done. 2. Static testing with grep to find parts of the kernel that call find_vma() (and other similar functions) or directly compare against vm_start/vm_end fields of vma. 3. Static testing with grep to find parts of the kernel that compare user pointers with TASK_SIZE or other similar consts and macros. 4. Dynamic testing: adding BUG_ON(has_tag(addr)) to find_vma() and running a modified syzkaller version that passes tagged pointers to the kernel. Based on the results of the testing the requried patches have been added to the patchset. === Notes This patchset is meant to be merged together with "arm64 relaxed ABI" [3]. This patchset is a prerequisite for ARM's memory tagging hardware feature support [4]. This patchset has been merged into the Pixel 2 kernel tree and is now being used to enable testing of Pixel 2 phones with HWASan. Thanks! [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html [2] https://github.com/lucvoo/sparse-dev/commit/5f960cb10f56ec2017c128ef9d16060e0145f292 [3] https://lkml.org/lkml/2019/3/18/819 [4] https://community.arm.com/processors/b/blog/posts/arm-a-profile-architecture-2018-developments-armv85a Changes in v12: - Changed untagging in tcp_zerocopy_receive() to also untag zc->address. - Fixed untagging in prctl_set_mm* to only untag pointers for vma lookups and validity checks, but leave them as is for actual user space accesses. - Updated the link to the v2 of the "arm64 relaxed ABI" patchset [3]. - Dropped the documentation patch, as the "arm64 relaxed ABI" patchset [3] handles that. Changes in v11: - Added "uprobes, arm64: untag user pointers in find_active_uprobe" patch. - Added "bpf, arm64: untag user pointers in stack_map_get_build_id_offset" patch. - Fixed "tracing, arm64: untag user pointers in seq_print_user_ip" to correctly perform subtration with a tagged addr. - Moved untagged_addr() from SYSCALL_DEFINE3(mprotect) and SYSCALL_DEFINE4(pkey_mprotect) to do_mprotect_pkey(). - Moved untagged_addr() definition for other arches from include/linux/memory.h to include/linux/mm.h. - Changed untagging in strn*_user() to perform userspace accesses through tagged pointers. - Updated the documentation to mention that passing tagged pointers to memory syscalls is allowed. - Updated the test to use malloc'ed memory instead of stack memory. Changes in v10: - Added "mm, arm64: untag user pointers passed to memory syscalls" back. - New patch "fs, arm64: untag user pointers in fs/userfaultfd.c". - New patch "net, arm64: untag user pointers in tcp_zerocopy_receive". - New patch "kernel, arm64: untag user pointers in prctl_set_mm*". - New patch "tracing, arm64: untag user pointers in seq_print_user_ip". Changes in v9: - Rebased onto 4.20-rc6. - Used u64 instead of __u64 in type casts in the untagged_addr macro for arm64. - Added braces around (addr) in the untagged_addr macro for other arches. Changes in v8: - Rebased onto 65102238 (4.20-rc1). - Added a note to the cover letter on why syscall wrappers/shims that untag user pointers won't work. - Added a note to the cover letter that this patchset has been merged into the Pixel 2 kernel tree. - Documentation fixes, in particular added a list of syscalls that don't support tagged user pointers. Changes in v7: - Rebased onto 17b57b18 (4.19-rc6). - Dropped the "arm64: untag user address in __do_user_fault" patch, since the existing patches already handle user faults properly. - Dropped the "usb, arm64: untag user addresses in devio" patch, since the passed pointer must come from a vma and therefore be untagged. - Dropped the "arm64: annotate user pointers casts detected by sparse" patch (see the discussion to the replies of the v6 of this patchset). - Added more context to the cover letter. - Updated Documentation/arm64/tagged-pointers.txt. Changes in v6: - Added annotations for user pointer casts found by sparse. - Rebased onto 050cdc6c (4.19-rc1+). Changes in v5: - Added 3 new patches that add untagging to places found with static analysis. - Rebased onto 44c929e1 (4.18-rc8). Changes in v4: - Added a selftest for checking that passing tagged pointers to the kernel succeeds. - Rebased onto 81e97f013 (4.18-rc1+). Changes in v3: - Rebased onto e5c51f30 (4.17-rc6+). - Added linux-arch@ to the list of recipients. Changes in v2: - Rebased onto 2d618bdf (4.17-rc3+). - Removed excessive untagging in gup.c. - Removed untagging pointers returned from __uaccess_mask_ptr. Changes in v1: - Rebased onto 4.17-rc1. Changes in RFC v2: - Added "#ifndef untagged_addr..." fallback in linux/uaccess.h instead of defining it for each arch individually. - Updated Documentation/arm64/tagged-pointers.txt. - Dropped "mm, arm64: untag user addresses in memory syscalls". - Rebased onto 3eb2ce82 (4.16-rc7). Signed-off-by: Andrey Konovalov Andrey Konovalov (13): uaccess: add untagged_addr definition for other arches arm64: untag user pointers in access_ok and __uaccess_mask_ptr lib, arm64: untag user pointers in strn*_user mm, arm64: untag user pointers passed to memory syscalls mm, arm64: untag user pointers in mm/gup.c fs, arm64: untag user pointers in copy_mount_options fs, arm64: untag user pointers in fs/userfaultfd.c net, arm64: untag user pointers in tcp_zerocopy_receive kernel, arm64: untag user pointers in prctl_set_mm* tracing, arm64: untag user pointers in seq_print_user_ip uprobes, arm64: untag user pointers in find_active_uprobe bpf, arm64: untag user pointers in stack_map_get_build_id_offset selftests, arm64: add a selftest for passing tagged pointers to kernel arch/arm64/include/asm/uaccess.h | 10 +++-- fs/namespace.c | 2 +- fs/userfaultfd.c | 5 +++ include/linux/mm.h | 4 ++ ipc/shm.c | 2 + kernel/bpf/stackmap.c | 6 ++- kernel/events/uprobes.c | 2 + kernel/sys.c | 44 +++++++++++++------ kernel/trace/trace_output.c | 5 ++- lib/strncpy_from_user.c | 3 +- lib/strnlen_user.c | 3 +- mm/gup.c | 4 ++ mm/madvise.c | 2 + mm/mempolicy.c | 5 +++ mm/migrate.c | 1 + mm/mincore.c | 2 + mm/mlock.c | 5 +++ mm/mmap.c | 7 +++ mm/mprotect.c | 1 + mm/mremap.c | 2 + mm/msync.c | 2 + net/ipv4/tcp.c | 9 +++- tools/testing/selftests/arm64/.gitignore | 1 + tools/testing/selftests/arm64/Makefile | 11 +++++ .../testing/selftests/arm64/run_tags_test.sh | 12 +++++ tools/testing/selftests/arm64/tags_test.c | 21 +++++++++ 26 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 tools/testing/selftests/arm64/.gitignore create mode 100644 tools/testing/selftests/arm64/Makefile create mode 100755 tools/testing/selftests/arm64/run_tags_test.sh create mode 100644 tools/testing/selftests/arm64/tags_test.c -- 2.21.0.225.g810b269d1ac-goog From mboxrd@z Thu Jan 1 00:00:00 1970 From: andreyknvl@google.com (Andrey Konovalov) Date: Mon, 18 Mar 2019 18:17:32 +0100 Subject: [PATCH v12 00/13] arm64: untag user pointers passed to the kernel Message-ID: Content-Type: text/plain; charset="UTF-8" Message-ID: <20190318171732.KE_oljkWVrigSh3cwwQwT4aVh-d773kjgFZazxd4Px0@z> === Overview arm64 has a feature called Top Byte Ignore, which allows to embed pointer tags into the top byte of each pointer. Userspace programs (such as HWASan, a memory debugging tool [1]) might use this feature and pass tagged user pointers to the kernel through syscalls or other interfaces. Right now the kernel is already able to handle user faults with tagged pointers, due to these patches: 1. 81cddd65 ("arm64: traps: fix userspace cache maintenance emulation on a tagged pointer") 2. 7dcd9dd8 ("arm64: hw_breakpoint: fix watchpoint matching for tagged pointers") 3. 276e9327 ("arm64: entry: improve data abort handling of tagged pointers") This patchset extends tagged pointer support to syscall arguments. As per the proposed ABI change [3], tagged pointers are only allowed to be passed to syscalls when they point to memory ranges obtained by anonymous mmap() or sbrk() (see the patchset [3] for more details). For non-memory syscalls this is done by untaging user pointers when the kernel performs pointer checking to find out whether the pointer comes from userspace (most notably in access_ok). The untagging is done only when the pointer is being checked, the tag is preserved as the pointer makes its way through the kernel and stays tagged when the kernel dereferences the pointer when perfoming user memory accesses. Memory syscalls (mmap, mprotect, etc.) don't do user memory accesses but rather deal with memory ranges, and untagged pointers are better suited to describe memory ranges internally. Thus for memory syscalls we untag pointers completely when they enter the kernel. === Other approaches One of the alternative approaches to untagging that was considered is to completely strip the pointer tag as the pointer enters the kernel with some kind of a syscall wrapper, but that won't work with the countless number of different ioctl calls. With this approach we would need a custom wrapper for each ioctl variation, which doesn't seem practical. An alternative approach to untagging pointers in memory syscalls prologues is to inspead allow tagged pointers to be passed to find_vma() (and other vma related functions) and untag them there. Unfortunately, a lot of find_vma() callers then compare or subtract the returned vma start and end fields against the pointer that was being searched. Thus this approach would still require changing all find_vma() callers. === Testing The following testing approaches has been taken to find potential issues with user pointer untagging: 1. Static testing (with sparse [2] and separately with a custom static analyzer based on Clang) to track casts of __user pointers to integer types to find places where untagging needs to be done. 2. Static testing with grep to find parts of the kernel that call find_vma() (and other similar functions) or directly compare against vm_start/vm_end fields of vma. 3. Static testing with grep to find parts of the kernel that compare user pointers with TASK_SIZE or other similar consts and macros. 4. Dynamic testing: adding BUG_ON(has_tag(addr)) to find_vma() and running a modified syzkaller version that passes tagged pointers to the kernel. Based on the results of the testing the requried patches have been added to the patchset. === Notes This patchset is meant to be merged together with "arm64 relaxed ABI" [3]. This patchset is a prerequisite for ARM's memory tagging hardware feature support [4]. This patchset has been merged into the Pixel 2 kernel tree and is now being used to enable testing of Pixel 2 phones with HWASan. Thanks! [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html [2] https://github.com/lucvoo/sparse-dev/commit/5f960cb10f56ec2017c128ef9d16060e0145f292 [3] https://lkml.org/lkml/2019/3/18/819 [4] https://community.arm.com/processors/b/blog/posts/arm-a-profile-architecture-2018-developments-armv85a Changes in v12: - Changed untagging in tcp_zerocopy_receive() to also untag zc->address. - Fixed untagging in prctl_set_mm* to only untag pointers for vma lookups and validity checks, but leave them as is for actual user space accesses. - Updated the link to the v2 of the "arm64 relaxed ABI" patchset [3]. - Dropped the documentation patch, as the "arm64 relaxed ABI" patchset [3] handles that. Changes in v11: - Added "uprobes, arm64: untag user pointers in find_active_uprobe" patch. - Added "bpf, arm64: untag user pointers in stack_map_get_build_id_offset" patch. - Fixed "tracing, arm64: untag user pointers in seq_print_user_ip" to correctly perform subtration with a tagged addr. - Moved untagged_addr() from SYSCALL_DEFINE3(mprotect) and SYSCALL_DEFINE4(pkey_mprotect) to do_mprotect_pkey(). - Moved untagged_addr() definition for other arches from include/linux/memory.h to include/linux/mm.h. - Changed untagging in strn*_user() to perform userspace accesses through tagged pointers. - Updated the documentation to mention that passing tagged pointers to memory syscalls is allowed. - Updated the test to use malloc'ed memory instead of stack memory. Changes in v10: - Added "mm, arm64: untag user pointers passed to memory syscalls" back. - New patch "fs, arm64: untag user pointers in fs/userfaultfd.c". - New patch "net, arm64: untag user pointers in tcp_zerocopy_receive". - New patch "kernel, arm64: untag user pointers in prctl_set_mm*". - New patch "tracing, arm64: untag user pointers in seq_print_user_ip". Changes in v9: - Rebased onto 4.20-rc6. - Used u64 instead of __u64 in type casts in the untagged_addr macro for arm64. - Added braces around (addr) in the untagged_addr macro for other arches. Changes in v8: - Rebased onto 65102238 (4.20-rc1). - Added a note to the cover letter on why syscall wrappers/shims that untag user pointers won't work. - Added a note to the cover letter that this patchset has been merged into the Pixel 2 kernel tree. - Documentation fixes, in particular added a list of syscalls that don't support tagged user pointers. Changes in v7: - Rebased onto 17b57b18 (4.19-rc6). - Dropped the "arm64: untag user address in __do_user_fault" patch, since the existing patches already handle user faults properly. - Dropped the "usb, arm64: untag user addresses in devio" patch, since the passed pointer must come from a vma and therefore be untagged. - Dropped the "arm64: annotate user pointers casts detected by sparse" patch (see the discussion to the replies of the v6 of this patchset). - Added more context to the cover letter. - Updated Documentation/arm64/tagged-pointers.txt. Changes in v6: - Added annotations for user pointer casts found by sparse. - Rebased onto 050cdc6c (4.19-rc1+). Changes in v5: - Added 3 new patches that add untagging to places found with static analysis. - Rebased onto 44c929e1 (4.18-rc8). Changes in v4: - Added a selftest for checking that passing tagged pointers to the kernel succeeds. - Rebased onto 81e97f013 (4.18-rc1+). Changes in v3: - Rebased onto e5c51f30 (4.17-rc6+). - Added linux-arch@ to the list of recipients. Changes in v2: - Rebased onto 2d618bdf (4.17-rc3+). - Removed excessive untagging in gup.c. - Removed untagging pointers returned from __uaccess_mask_ptr. Changes in v1: - Rebased onto 4.17-rc1. Changes in RFC v2: - Added "#ifndef untagged_addr..." fallback in linux/uaccess.h instead of defining it for each arch individually. - Updated Documentation/arm64/tagged-pointers.txt. - Dropped "mm, arm64: untag user addresses in memory syscalls". - Rebased onto 3eb2ce82 (4.16-rc7). Signed-off-by: Andrey Konovalov Andrey Konovalov (13): uaccess: add untagged_addr definition for other arches arm64: untag user pointers in access_ok and __uaccess_mask_ptr lib, arm64: untag user pointers in strn*_user mm, arm64: untag user pointers passed to memory syscalls mm, arm64: untag user pointers in mm/gup.c fs, arm64: untag user pointers in copy_mount_options fs, arm64: untag user pointers in fs/userfaultfd.c net, arm64: untag user pointers in tcp_zerocopy_receive kernel, arm64: untag user pointers in prctl_set_mm* tracing, arm64: untag user pointers in seq_print_user_ip uprobes, arm64: untag user pointers in find_active_uprobe bpf, arm64: untag user pointers in stack_map_get_build_id_offset selftests, arm64: add a selftest for passing tagged pointers to kernel arch/arm64/include/asm/uaccess.h | 10 +++-- fs/namespace.c | 2 +- fs/userfaultfd.c | 5 +++ include/linux/mm.h | 4 ++ ipc/shm.c | 2 + kernel/bpf/stackmap.c | 6 ++- kernel/events/uprobes.c | 2 + kernel/sys.c | 44 +++++++++++++------ kernel/trace/trace_output.c | 5 ++- lib/strncpy_from_user.c | 3 +- lib/strnlen_user.c | 3 +- mm/gup.c | 4 ++ mm/madvise.c | 2 + mm/mempolicy.c | 5 +++ mm/migrate.c | 1 + mm/mincore.c | 2 + mm/mlock.c | 5 +++ mm/mmap.c | 7 +++ mm/mprotect.c | 1 + mm/mremap.c | 2 + mm/msync.c | 2 + net/ipv4/tcp.c | 9 +++- tools/testing/selftests/arm64/.gitignore | 1 + tools/testing/selftests/arm64/Makefile | 11 +++++ .../testing/selftests/arm64/run_tags_test.sh | 12 +++++ tools/testing/selftests/arm64/tags_test.c | 21 +++++++++ 26 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 tools/testing/selftests/arm64/.gitignore create mode 100644 tools/testing/selftests/arm64/Makefile create mode 100755 tools/testing/selftests/arm64/run_tags_test.sh create mode 100644 tools/testing/selftests/arm64/tags_test.c -- 2.21.0.225.g810b269d1ac-goog 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=-18.6 required=3.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_PASS,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 5D4F4C43381 for ; Mon, 18 Mar 2019 17:17:52 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 003B620863 for ; Mon, 18 Mar 2019 17:17:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="r7BuUjT8" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 003B620863 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 6FC396B0003; Mon, 18 Mar 2019 13:17:51 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 6875B6B0006; Mon, 18 Mar 2019 13:17:51 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 54F5B6B0007; Mon, 18 Mar 2019 13:17:51 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by kanga.kvack.org (Postfix) with ESMTP id 2F8F06B0003 for ; Mon, 18 Mar 2019 13:17:51 -0400 (EDT) Received: by mail-qt1-f197.google.com with SMTP id d49so4349479qtk.8 for ; Mon, 18 Mar 2019 10:17:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:dkim-signature:date:message-id:mime-version :subject:from:to:cc; bh=hkZRyLCyEaEj0h1/8UX44FTe5HP+CD8YXp42TcJT5X4=; b=pwELSv0UnH4Xt+beJN0KXewQXQE6/K2p9Snw1CMw5Wjw5EvpifpQ3e4qGu7zF5VR6E tCMu/1hLwnSICHDFprJn7rBwsDFdt/18IjQFsqy3zx/5s1yqcGZDl/SCZNqNItF5VDjM glJyTheuy8/PeQq/msYgMgvXwLd9LIuWQmuyhmhp0cVxinU00l5UkT9PVyNAXp9kwCX7 59ymksqiyncexYaigpaTQpH4k6Kdwfdh1n8SR/N227QdMwaRISky2wHQDYAPvK0jH8Pi mjouWSXQwzTYb85L+Tu60BbVyOdw3RobMl/LThOqZgY48TKpLAYK7LHn/KTlJrjyfUiP 7CMQ== X-Gm-Message-State: APjAAAUYr/iTQuc+ZixOLfAHNHMZ75GPQAK2mc52esvDLPcwrG5Dd/L1 GC2u+NO52oLTBwpwZOvrgaAh6NN2/QKevwErixDjazoMZyqGaGL5E/lYhnTYeSWVT9YYEllD6u9 ZFO94oRPYV8AGypYQrcb4fKFSWhwhWdWvValbkCkqssYDcEXNBDkoZD918mV6qR/zrQ== X-Received: by 2002:ac8:f6e:: with SMTP id l43mr7586002qtk.322.1552929470881; Mon, 18 Mar 2019 10:17:50 -0700 (PDT) X-Received: by 2002:ac8:f6e:: with SMTP id l43mr7585919qtk.322.1552929469556; Mon, 18 Mar 2019 10:17:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1552929469; cv=none; d=google.com; s=arc-20160816; b=cVe4LuPHmzhav0M/texaoibA87mKfFplQ/jBWnTwDwQxnk/DdvT/+W38FKiXsmtn8e ByxZ/NdZ84mukE/o/U1EnDvKRmwjA/Zh3oJlfad4TYe/wVNyBbBi9bfGFBSTYC/0GiQ/ l90yMCZ1CvnrkMgfb5Ruj5V3oc/u60j5JrM+DNYt0mRVgQ2n0QBTV/zhBmJ7lDE/tShW gU8FKneVuYPwzA1idZPd1qbIQcpFsV0Y5Ia3819cVUBAbPHDco684OmHgB4UNhZQKiPn IcWvh9W7JSEDbnKWS1EjTlvDOVKGtctT0vm3kgApv0mTQUJqP720I0THwoTLL6VusdnC mXbA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:mime-version:message-id:date:dkim-signature; bh=hkZRyLCyEaEj0h1/8UX44FTe5HP+CD8YXp42TcJT5X4=; b=ofKs4606kqDiWg+afvIrvWYP0YHy03XjwIsQHVm6lkC3II4jt6xRFk/Gh4v5VilIXj Oy5cus3sJLLE8FiAAOfcxmBNPmW5aZ3GZpIOjQorHg5Jamm8lJ+5CmDJ6ytbyoOXoraz +ZHuWhwtN2JqFt9x3xJTZdoJe7PFhWwdGuP/ferPwrM8j7FtCs04Ngxt6QOH6Ksdcb9X URw34Umt5nn3s03JG916Di6TTdikfZWaHZN8XVtx5rEFuOUOK5dbd+fE08AQYyLvFWhu odZqGNUlnIwWunGnOdMLBqWjWgD+upHtkxnHyAp8f8d/W2xptsO6+7OeY8YNYkwgOLxN ymFQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=r7BuUjT8; spf=pass (google.com: domain of 3vnkpxaokcisp2s6tdz2a0v33v0t.r310x29c-11zaprz.36v@flex--andreyknvl.bounces.google.com designates 209.85.220.73 as permitted sender) smtp.mailfrom=3vNKPXAoKCIsp2s6tDz2A0v33v0t.r310x29C-11zAprz.36v@flex--andreyknvl.bounces.google.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from mail-sor-f73.google.com (mail-sor-f73.google.com. [209.85.220.73]) by mx.google.com with SMTPS id d22sor12622519qto.42.2019.03.18.10.17.49 for (Google Transport Security); Mon, 18 Mar 2019 10:17:49 -0700 (PDT) Received-SPF: pass (google.com: domain of 3vnkpxaokcisp2s6tdz2a0v33v0t.r310x29c-11zaprz.36v@flex--andreyknvl.bounces.google.com designates 209.85.220.73 as permitted sender) client-ip=209.85.220.73; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=r7BuUjT8; spf=pass (google.com: domain of 3vnkpxaokcisp2s6tdz2a0v33v0t.r310x29c-11zaprz.36v@flex--andreyknvl.bounces.google.com designates 209.85.220.73 as permitted sender) smtp.mailfrom=3vNKPXAoKCIsp2s6tDz2A0v33v0t.r310x29C-11zAprz.36v@flex--andreyknvl.bounces.google.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=hkZRyLCyEaEj0h1/8UX44FTe5HP+CD8YXp42TcJT5X4=; b=r7BuUjT872vqMsVH/wkX0rjSoIhlckZYzTG8nkCBzc21HrrSP19mTaFG7c/ZUIfgAD lzqbtolzZhCEXgEjV5Dc9Xqs/UljOaAvtRhFVaA0zAgNWOvDVrOZTK86tNsjly501M+i AYUz5hIxJkGAK0BJCTA9Td2ckq1vEAjsrtDJj2d9NzWPTchq1PPgOx/JRG7fniXo3qP0 xXd+E9EBHtRgO2gNveThVNHJyyTj8PAxfe+1vn5XX4QV2ryXVMc7CcdeCwHwF1bZ7hSF 6ayQgkhu3GgiLEigUaW9xs5aq5tzxIZ+FvU/WGxFOfLlXMKdaCJOzaCW9E06Em0uNsw4 0W3A== X-Google-Smtp-Source: APXvYqzkeAXzAy3oNYG2BR4miR/Z8Fu9oC+SjuURt/xYQhyeLrh/e+rUUiZ2TAsT5ZCM3sbUSVpsZp73cydX3AZ1 X-Received: by 2002:ac8:21f2:: with SMTP id 47mr10992908qtz.9.1552929468913; Mon, 18 Mar 2019 10:17:48 -0700 (PDT) Date: Mon, 18 Mar 2019 18:17:32 +0100 Message-Id: Mime-Version: 1.0 X-Mailer: git-send-email 2.21.0.225.g810b269d1ac-goog Subject: [PATCH v12 00/13] arm64: untag user pointers passed to the kernel From: Andrey Konovalov To: Catalin Marinas , Will Deacon , Mark Rutland , Robin Murphy , Kees Cook , Kate Stewart , Greg Kroah-Hartman , Andrew Morton , Ingo Molnar , "Kirill A . Shutemov" , Shuah Khan , Vincenzo Frascino , Eric Dumazet , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , Steven Rostedt , Ingo Molnar , Peter Zijlstra , Arnaldo Carvalho de Melo , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Dmitry Vyukov , Kostya Serebryany , Evgeniy Stepanov , Lee Smith , Ramana Radhakrishnan , Jacob Bramley , Ruben Ayrapetyan , Chintan Pandya , Luc Van Oostenryck , Dave Martin , Kevin Brodsky , Szabolcs Nagy , Andrey Konovalov Content-Type: text/plain; charset="UTF-8" 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: === Overview arm64 has a feature called Top Byte Ignore, which allows to embed pointer tags into the top byte of each pointer. Userspace programs (such as HWASan, a memory debugging tool [1]) might use this feature and pass tagged user pointers to the kernel through syscalls or other interfaces. Right now the kernel is already able to handle user faults with tagged pointers, due to these patches: 1. 81cddd65 ("arm64: traps: fix userspace cache maintenance emulation on a tagged pointer") 2. 7dcd9dd8 ("arm64: hw_breakpoint: fix watchpoint matching for tagged pointers") 3. 276e9327 ("arm64: entry: improve data abort handling of tagged pointers") This patchset extends tagged pointer support to syscall arguments. As per the proposed ABI change [3], tagged pointers are only allowed to be passed to syscalls when they point to memory ranges obtained by anonymous mmap() or sbrk() (see the patchset [3] for more details). For non-memory syscalls this is done by untaging user pointers when the kernel performs pointer checking to find out whether the pointer comes from userspace (most notably in access_ok). The untagging is done only when the pointer is being checked, the tag is preserved as the pointer makes its way through the kernel and stays tagged when the kernel dereferences the pointer when perfoming user memory accesses. Memory syscalls (mmap, mprotect, etc.) don't do user memory accesses but rather deal with memory ranges, and untagged pointers are better suited to describe memory ranges internally. Thus for memory syscalls we untag pointers completely when they enter the kernel. === Other approaches One of the alternative approaches to untagging that was considered is to completely strip the pointer tag as the pointer enters the kernel with some kind of a syscall wrapper, but that won't work with the countless number of different ioctl calls. With this approach we would need a custom wrapper for each ioctl variation, which doesn't seem practical. An alternative approach to untagging pointers in memory syscalls prologues is to inspead allow tagged pointers to be passed to find_vma() (and other vma related functions) and untag them there. Unfortunately, a lot of find_vma() callers then compare or subtract the returned vma start and end fields against the pointer that was being searched. Thus this approach would still require changing all find_vma() callers. === Testing The following testing approaches has been taken to find potential issues with user pointer untagging: 1. Static testing (with sparse [2] and separately with a custom static analyzer based on Clang) to track casts of __user pointers to integer types to find places where untagging needs to be done. 2. Static testing with grep to find parts of the kernel that call find_vma() (and other similar functions) or directly compare against vm_start/vm_end fields of vma. 3. Static testing with grep to find parts of the kernel that compare user pointers with TASK_SIZE or other similar consts and macros. 4. Dynamic testing: adding BUG_ON(has_tag(addr)) to find_vma() and running a modified syzkaller version that passes tagged pointers to the kernel. Based on the results of the testing the requried patches have been added to the patchset. === Notes This patchset is meant to be merged together with "arm64 relaxed ABI" [3]. This patchset is a prerequisite for ARM's memory tagging hardware feature support [4]. This patchset has been merged into the Pixel 2 kernel tree and is now being used to enable testing of Pixel 2 phones with HWASan. Thanks! [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html [2] https://github.com/lucvoo/sparse-dev/commit/5f960cb10f56ec2017c128ef9d16060e0145f292 [3] https://lkml.org/lkml/2019/3/18/819 [4] https://community.arm.com/processors/b/blog/posts/arm-a-profile-architecture-2018-developments-armv85a Changes in v12: - Changed untagging in tcp_zerocopy_receive() to also untag zc->address. - Fixed untagging in prctl_set_mm* to only untag pointers for vma lookups and validity checks, but leave them as is for actual user space accesses. - Updated the link to the v2 of the "arm64 relaxed ABI" patchset [3]. - Dropped the documentation patch, as the "arm64 relaxed ABI" patchset [3] handles that. Changes in v11: - Added "uprobes, arm64: untag user pointers in find_active_uprobe" patch. - Added "bpf, arm64: untag user pointers in stack_map_get_build_id_offset" patch. - Fixed "tracing, arm64: untag user pointers in seq_print_user_ip" to correctly perform subtration with a tagged addr. - Moved untagged_addr() from SYSCALL_DEFINE3(mprotect) and SYSCALL_DEFINE4(pkey_mprotect) to do_mprotect_pkey(). - Moved untagged_addr() definition for other arches from include/linux/memory.h to include/linux/mm.h. - Changed untagging in strn*_user() to perform userspace accesses through tagged pointers. - Updated the documentation to mention that passing tagged pointers to memory syscalls is allowed. - Updated the test to use malloc'ed memory instead of stack memory. Changes in v10: - Added "mm, arm64: untag user pointers passed to memory syscalls" back. - New patch "fs, arm64: untag user pointers in fs/userfaultfd.c". - New patch "net, arm64: untag user pointers in tcp_zerocopy_receive". - New patch "kernel, arm64: untag user pointers in prctl_set_mm*". - New patch "tracing, arm64: untag user pointers in seq_print_user_ip". Changes in v9: - Rebased onto 4.20-rc6. - Used u64 instead of __u64 in type casts in the untagged_addr macro for arm64. - Added braces around (addr) in the untagged_addr macro for other arches. Changes in v8: - Rebased onto 65102238 (4.20-rc1). - Added a note to the cover letter on why syscall wrappers/shims that untag user pointers won't work. - Added a note to the cover letter that this patchset has been merged into the Pixel 2 kernel tree. - Documentation fixes, in particular added a list of syscalls that don't support tagged user pointers. Changes in v7: - Rebased onto 17b57b18 (4.19-rc6). - Dropped the "arm64: untag user address in __do_user_fault" patch, since the existing patches already handle user faults properly. - Dropped the "usb, arm64: untag user addresses in devio" patch, since the passed pointer must come from a vma and therefore be untagged. - Dropped the "arm64: annotate user pointers casts detected by sparse" patch (see the discussion to the replies of the v6 of this patchset). - Added more context to the cover letter. - Updated Documentation/arm64/tagged-pointers.txt. Changes in v6: - Added annotations for user pointer casts found by sparse. - Rebased onto 050cdc6c (4.19-rc1+). Changes in v5: - Added 3 new patches that add untagging to places found with static analysis. - Rebased onto 44c929e1 (4.18-rc8). Changes in v4: - Added a selftest for checking that passing tagged pointers to the kernel succeeds. - Rebased onto 81e97f013 (4.18-rc1+). Changes in v3: - Rebased onto e5c51f30 (4.17-rc6+). - Added linux-arch@ to the list of recipients. Changes in v2: - Rebased onto 2d618bdf (4.17-rc3+). - Removed excessive untagging in gup.c. - Removed untagging pointers returned from __uaccess_mask_ptr. Changes in v1: - Rebased onto 4.17-rc1. Changes in RFC v2: - Added "#ifndef untagged_addr..." fallback in linux/uaccess.h instead of defining it for each arch individually. - Updated Documentation/arm64/tagged-pointers.txt. - Dropped "mm, arm64: untag user addresses in memory syscalls". - Rebased onto 3eb2ce82 (4.16-rc7). Signed-off-by: Andrey Konovalov Andrey Konovalov (13): uaccess: add untagged_addr definition for other arches arm64: untag user pointers in access_ok and __uaccess_mask_ptr lib, arm64: untag user pointers in strn*_user mm, arm64: untag user pointers passed to memory syscalls mm, arm64: untag user pointers in mm/gup.c fs, arm64: untag user pointers in copy_mount_options fs, arm64: untag user pointers in fs/userfaultfd.c net, arm64: untag user pointers in tcp_zerocopy_receive kernel, arm64: untag user pointers in prctl_set_mm* tracing, arm64: untag user pointers in seq_print_user_ip uprobes, arm64: untag user pointers in find_active_uprobe bpf, arm64: untag user pointers in stack_map_get_build_id_offset selftests, arm64: add a selftest for passing tagged pointers to kernel arch/arm64/include/asm/uaccess.h | 10 +++-- fs/namespace.c | 2 +- fs/userfaultfd.c | 5 +++ include/linux/mm.h | 4 ++ ipc/shm.c | 2 + kernel/bpf/stackmap.c | 6 ++- kernel/events/uprobes.c | 2 + kernel/sys.c | 44 +++++++++++++------ kernel/trace/trace_output.c | 5 ++- lib/strncpy_from_user.c | 3 +- lib/strnlen_user.c | 3 +- mm/gup.c | 4 ++ mm/madvise.c | 2 + mm/mempolicy.c | 5 +++ mm/migrate.c | 1 + mm/mincore.c | 2 + mm/mlock.c | 5 +++ mm/mmap.c | 7 +++ mm/mprotect.c | 1 + mm/mremap.c | 2 + mm/msync.c | 2 + net/ipv4/tcp.c | 9 +++- tools/testing/selftests/arm64/.gitignore | 1 + tools/testing/selftests/arm64/Makefile | 11 +++++ .../testing/selftests/arm64/run_tags_test.sh | 12 +++++ tools/testing/selftests/arm64/tags_test.c | 21 +++++++++ 26 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 tools/testing/selftests/arm64/.gitignore create mode 100644 tools/testing/selftests/arm64/Makefile create mode 100755 tools/testing/selftests/arm64/run_tags_test.sh create mode 100644 tools/testing/selftests/arm64/tags_test.c -- 2.21.0.225.g810b269d1ac-goog 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=-11.0 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable 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 85C6AC10F00 for ; Mon, 18 Mar 2019 17:18:04 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 561C321741 for ; Mon, 18 Mar 2019 17:18:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="VF74cwPG"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="r7BuUjT8" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 561C321741 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:To:From:Subject:Mime-Version:Message-Id :Date:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=+mBHDsD8+m7xGPpSHTy+45hqMskFsvzen2hNaa/rKx4=; b=VF74cwPGk1R8pi D7sx2bSrQG7hjgJw7jdLBZ+eHF0Le/dUmml+wGJk9W/CtiKcBMIn8QlH0MyaCOO723MjsQ1l/tAsE iuEydW3AMg36A+QtN2uo/qlll3qwWSBOzjw/4Aqx/fcQ2DUgB10jH9tQj47bNoYb9D7sMnKSbYay1 KIWuJEtLk7GROCngtZOhopxg+0ORRRfD2vN8IdAzyGC0QnoUqV8SN3hJwnLrBU9ztg7VnrIKieNAC 6vf16D4MU+Cm734iR1JrjSC0VnDefAI8bCTaiiP4Pb1t7nKbD0aKNwqR3FqBccOeeqoer6bsUiPYp VPeBXICHLsbiiur2BIFg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h5vtb-0002fU-K0; Mon, 18 Mar 2019 17:17:55 +0000 Received: from mail-qk1-x749.google.com ([2607:f8b0:4864:20::749]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1h5vtX-0002dI-E4 for linux-arm-kernel@lists.infradead.org; Mon, 18 Mar 2019 17:17:54 +0000 Received: by mail-qk1-x749.google.com with SMTP id w134so15209048qka.6 for ; Mon, 18 Mar 2019 10:17:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=hkZRyLCyEaEj0h1/8UX44FTe5HP+CD8YXp42TcJT5X4=; b=r7BuUjT872vqMsVH/wkX0rjSoIhlckZYzTG8nkCBzc21HrrSP19mTaFG7c/ZUIfgAD lzqbtolzZhCEXgEjV5Dc9Xqs/UljOaAvtRhFVaA0zAgNWOvDVrOZTK86tNsjly501M+i AYUz5hIxJkGAK0BJCTA9Td2ckq1vEAjsrtDJj2d9NzWPTchq1PPgOx/JRG7fniXo3qP0 xXd+E9EBHtRgO2gNveThVNHJyyTj8PAxfe+1vn5XX4QV2ryXVMc7CcdeCwHwF1bZ7hSF 6ayQgkhu3GgiLEigUaW9xs5aq5tzxIZ+FvU/WGxFOfLlXMKdaCJOzaCW9E06Em0uNsw4 0W3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=hkZRyLCyEaEj0h1/8UX44FTe5HP+CD8YXp42TcJT5X4=; b=lSmFYCHeoUWu+2tRQv0zn8RACYASuDIyfxf3hR9hK8Pk85SbIudefugVhzXlgK0sNV qG7F1cxFwOGmiY8IZIeaIUCT7eLMUEATjS8Rqz1EnGCA5TpeXHmpotDr7kMPI9Educ/8 BxiEnfboqbGAmYNLREffz9Jf4L2vOaugsnc1FfcM+8kW4Ig8NpytxP3KfjGv3yDNLCff 8tjLDfexVqRdZh0R3hJCfhsKdJD5aEjdU3NVIkceOIiNwBf6n2aEZtp0bKALeK/xBjKu pnmWexFLrDrSCDrHODXQPdVd/Kv/WOHy5l1pvxG987IUYG6nLb7SQzWuYPbQNuFU2gwW 90NA== X-Gm-Message-State: APjAAAWEvK0HZf5FbBoKe6ClkLHbObt9aZWzkP5mCGA4hqQBx3Hby2xO 8LE0vvs/VBp1r5Dt9HAhm4CsknsgtodCOdNe X-Google-Smtp-Source: APXvYqzkeAXzAy3oNYG2BR4miR/Z8Fu9oC+SjuURt/xYQhyeLrh/e+rUUiZ2TAsT5ZCM3sbUSVpsZp73cydX3AZ1 X-Received: by 2002:ac8:21f2:: with SMTP id 47mr10992908qtz.9.1552929468913; Mon, 18 Mar 2019 10:17:48 -0700 (PDT) Date: Mon, 18 Mar 2019 18:17:32 +0100 Message-Id: Mime-Version: 1.0 X-Mailer: git-send-email 2.21.0.225.g810b269d1ac-goog Subject: [PATCH v12 00/13] arm64: untag user pointers passed to the kernel From: Andrey Konovalov To: Catalin Marinas , Will Deacon , Mark Rutland , Robin Murphy , Kees Cook , Kate Stewart , Greg Kroah-Hartman , Andrew Morton , Ingo Molnar , "Kirill A . Shutemov" , Shuah Khan , Vincenzo Frascino , Eric Dumazet , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , Steven Rostedt , Ingo Molnar , Peter Zijlstra , Arnaldo Carvalho de Melo , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190318_101751_502563_9795E2BE X-CRM114-Status: GOOD ( 25.99 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Brodsky , Chintan Pandya , Jacob Bramley , Ruben Ayrapetyan , Szabolcs Nagy , Andrey Konovalov , Lee Smith , Kostya Serebryany , Dmitry Vyukov , Ramana Radhakrishnan , Luc Van Oostenryck , Dave Martin , Evgeniy Stepanov Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org === Overview arm64 has a feature called Top Byte Ignore, which allows to embed pointer tags into the top byte of each pointer. Userspace programs (such as HWASan, a memory debugging tool [1]) might use this feature and pass tagged user pointers to the kernel through syscalls or other interfaces. Right now the kernel is already able to handle user faults with tagged pointers, due to these patches: 1. 81cddd65 ("arm64: traps: fix userspace cache maintenance emulation on a tagged pointer") 2. 7dcd9dd8 ("arm64: hw_breakpoint: fix watchpoint matching for tagged pointers") 3. 276e9327 ("arm64: entry: improve data abort handling of tagged pointers") This patchset extends tagged pointer support to syscall arguments. As per the proposed ABI change [3], tagged pointers are only allowed to be passed to syscalls when they point to memory ranges obtained by anonymous mmap() or sbrk() (see the patchset [3] for more details). For non-memory syscalls this is done by untaging user pointers when the kernel performs pointer checking to find out whether the pointer comes from userspace (most notably in access_ok). The untagging is done only when the pointer is being checked, the tag is preserved as the pointer makes its way through the kernel and stays tagged when the kernel dereferences the pointer when perfoming user memory accesses. Memory syscalls (mmap, mprotect, etc.) don't do user memory accesses but rather deal with memory ranges, and untagged pointers are better suited to describe memory ranges internally. Thus for memory syscalls we untag pointers completely when they enter the kernel. === Other approaches One of the alternative approaches to untagging that was considered is to completely strip the pointer tag as the pointer enters the kernel with some kind of a syscall wrapper, but that won't work with the countless number of different ioctl calls. With this approach we would need a custom wrapper for each ioctl variation, which doesn't seem practical. An alternative approach to untagging pointers in memory syscalls prologues is to inspead allow tagged pointers to be passed to find_vma() (and other vma related functions) and untag them there. Unfortunately, a lot of find_vma() callers then compare or subtract the returned vma start and end fields against the pointer that was being searched. Thus this approach would still require changing all find_vma() callers. === Testing The following testing approaches has been taken to find potential issues with user pointer untagging: 1. Static testing (with sparse [2] and separately with a custom static analyzer based on Clang) to track casts of __user pointers to integer types to find places where untagging needs to be done. 2. Static testing with grep to find parts of the kernel that call find_vma() (and other similar functions) or directly compare against vm_start/vm_end fields of vma. 3. Static testing with grep to find parts of the kernel that compare user pointers with TASK_SIZE or other similar consts and macros. 4. Dynamic testing: adding BUG_ON(has_tag(addr)) to find_vma() and running a modified syzkaller version that passes tagged pointers to the kernel. Based on the results of the testing the requried patches have been added to the patchset. === Notes This patchset is meant to be merged together with "arm64 relaxed ABI" [3]. This patchset is a prerequisite for ARM's memory tagging hardware feature support [4]. This patchset has been merged into the Pixel 2 kernel tree and is now being used to enable testing of Pixel 2 phones with HWASan. Thanks! [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html [2] https://github.com/lucvoo/sparse-dev/commit/5f960cb10f56ec2017c128ef9d16060e0145f292 [3] https://lkml.org/lkml/2019/3/18/819 [4] https://community.arm.com/processors/b/blog/posts/arm-a-profile-architecture-2018-developments-armv85a Changes in v12: - Changed untagging in tcp_zerocopy_receive() to also untag zc->address. - Fixed untagging in prctl_set_mm* to only untag pointers for vma lookups and validity checks, but leave them as is for actual user space accesses. - Updated the link to the v2 of the "arm64 relaxed ABI" patchset [3]. - Dropped the documentation patch, as the "arm64 relaxed ABI" patchset [3] handles that. Changes in v11: - Added "uprobes, arm64: untag user pointers in find_active_uprobe" patch. - Added "bpf, arm64: untag user pointers in stack_map_get_build_id_offset" patch. - Fixed "tracing, arm64: untag user pointers in seq_print_user_ip" to correctly perform subtration with a tagged addr. - Moved untagged_addr() from SYSCALL_DEFINE3(mprotect) and SYSCALL_DEFINE4(pkey_mprotect) to do_mprotect_pkey(). - Moved untagged_addr() definition for other arches from include/linux/memory.h to include/linux/mm.h. - Changed untagging in strn*_user() to perform userspace accesses through tagged pointers. - Updated the documentation to mention that passing tagged pointers to memory syscalls is allowed. - Updated the test to use malloc'ed memory instead of stack memory. Changes in v10: - Added "mm, arm64: untag user pointers passed to memory syscalls" back. - New patch "fs, arm64: untag user pointers in fs/userfaultfd.c". - New patch "net, arm64: untag user pointers in tcp_zerocopy_receive". - New patch "kernel, arm64: untag user pointers in prctl_set_mm*". - New patch "tracing, arm64: untag user pointers in seq_print_user_ip". Changes in v9: - Rebased onto 4.20-rc6. - Used u64 instead of __u64 in type casts in the untagged_addr macro for arm64. - Added braces around (addr) in the untagged_addr macro for other arches. Changes in v8: - Rebased onto 65102238 (4.20-rc1). - Added a note to the cover letter on why syscall wrappers/shims that untag user pointers won't work. - Added a note to the cover letter that this patchset has been merged into the Pixel 2 kernel tree. - Documentation fixes, in particular added a list of syscalls that don't support tagged user pointers. Changes in v7: - Rebased onto 17b57b18 (4.19-rc6). - Dropped the "arm64: untag user address in __do_user_fault" patch, since the existing patches already handle user faults properly. - Dropped the "usb, arm64: untag user addresses in devio" patch, since the passed pointer must come from a vma and therefore be untagged. - Dropped the "arm64: annotate user pointers casts detected by sparse" patch (see the discussion to the replies of the v6 of this patchset). - Added more context to the cover letter. - Updated Documentation/arm64/tagged-pointers.txt. Changes in v6: - Added annotations for user pointer casts found by sparse. - Rebased onto 050cdc6c (4.19-rc1+). Changes in v5: - Added 3 new patches that add untagging to places found with static analysis. - Rebased onto 44c929e1 (4.18-rc8). Changes in v4: - Added a selftest for checking that passing tagged pointers to the kernel succeeds. - Rebased onto 81e97f013 (4.18-rc1+). Changes in v3: - Rebased onto e5c51f30 (4.17-rc6+). - Added linux-arch@ to the list of recipients. Changes in v2: - Rebased onto 2d618bdf (4.17-rc3+). - Removed excessive untagging in gup.c. - Removed untagging pointers returned from __uaccess_mask_ptr. Changes in v1: - Rebased onto 4.17-rc1. Changes in RFC v2: - Added "#ifndef untagged_addr..." fallback in linux/uaccess.h instead of defining it for each arch individually. - Updated Documentation/arm64/tagged-pointers.txt. - Dropped "mm, arm64: untag user addresses in memory syscalls". - Rebased onto 3eb2ce82 (4.16-rc7). Signed-off-by: Andrey Konovalov Andrey Konovalov (13): uaccess: add untagged_addr definition for other arches arm64: untag user pointers in access_ok and __uaccess_mask_ptr lib, arm64: untag user pointers in strn*_user mm, arm64: untag user pointers passed to memory syscalls mm, arm64: untag user pointers in mm/gup.c fs, arm64: untag user pointers in copy_mount_options fs, arm64: untag user pointers in fs/userfaultfd.c net, arm64: untag user pointers in tcp_zerocopy_receive kernel, arm64: untag user pointers in prctl_set_mm* tracing, arm64: untag user pointers in seq_print_user_ip uprobes, arm64: untag user pointers in find_active_uprobe bpf, arm64: untag user pointers in stack_map_get_build_id_offset selftests, arm64: add a selftest for passing tagged pointers to kernel arch/arm64/include/asm/uaccess.h | 10 +++-- fs/namespace.c | 2 +- fs/userfaultfd.c | 5 +++ include/linux/mm.h | 4 ++ ipc/shm.c | 2 + kernel/bpf/stackmap.c | 6 ++- kernel/events/uprobes.c | 2 + kernel/sys.c | 44 +++++++++++++------ kernel/trace/trace_output.c | 5 ++- lib/strncpy_from_user.c | 3 +- lib/strnlen_user.c | 3 +- mm/gup.c | 4 ++ mm/madvise.c | 2 + mm/mempolicy.c | 5 +++ mm/migrate.c | 1 + mm/mincore.c | 2 + mm/mlock.c | 5 +++ mm/mmap.c | 7 +++ mm/mprotect.c | 1 + mm/mremap.c | 2 + mm/msync.c | 2 + net/ipv4/tcp.c | 9 +++- tools/testing/selftests/arm64/.gitignore | 1 + tools/testing/selftests/arm64/Makefile | 11 +++++ .../testing/selftests/arm64/run_tags_test.sh | 12 +++++ tools/testing/selftests/arm64/tags_test.c | 21 +++++++++ 26 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 tools/testing/selftests/arm64/.gitignore create mode 100644 tools/testing/selftests/arm64/Makefile create mode 100755 tools/testing/selftests/arm64/run_tags_test.sh create mode 100644 tools/testing/selftests/arm64/tags_test.c -- 2.21.0.225.g810b269d1ac-goog _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel