diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index e77baba..8470947 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -9,30 +9,14 @@ on:
jobs:
build-ubuntu-gcc:
runs-on: ubuntu-latest
- strategy:
- matrix:
- version: [12, 13, 14]
steps:
- uses: actions/checkout@v4
- - name: Setting up gcc version
- run: |
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${{ matrix.version }} 100
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ matrix.version }} 100
- name: Build
run: make test
build-ubuntu-clang:
runs-on: ubuntu-latest
- strategy:
- matrix:
- version: [14, 15, 16, 17, 18]
steps:
- uses: actions/checkout@v4
- - name: Install dependencies
- run: sudo apt-get update && sudo apt-get install -y --no-install-recommends clang-14 clang-15
- - name: Setting up clang version
- run: |
- sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${{ matrix.version }} 100
- sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${{ matrix.version }} 100
- name: Build
run: CC=clang CXX=clang++ make test
build-musl:
diff --git a/Android.bp b/Android.bp
index f6a7a9c..11725a6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -5,6 +5,8 @@ common_cflags = [
"-fPIC",
"-fvisibility=hidden",
//"-fno-plt",
+ "-Wall",
+ "-Wextra",
"-Wcast-align",
"-Wcast-qual",
"-Wwrite-strings",
@@ -71,9 +73,6 @@ cc_library {
debuggable: {
cflags: ["-DLABEL_MEMORY"],
},
- device_has_arm_mte: {
- cflags: ["-DHAS_ARM_MTE", "-march=armv8-a+dotprod+memtag"]
- },
},
apex_available: [
"com.android.runtime",
diff --git a/CREDITS b/CREDITS
index 31b6875..3ad8617 100644
--- a/CREDITS
+++ b/CREDITS
@@ -54,230 +54,3 @@ libdivide:
random.c get_random_{type}_uniform functions are based on Fast Random Integer
Generation in an Interval by Daniel Lemire
-
-arm_mte.h arm_mte_tag_and_clear_mem function contents were copied from storeTags function in scudo:
-
- ==============================================================================
- The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
- ==============================================================================
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
- ---- LLVM Exceptions to the Apache 2.0 License ----
-
- As an exception, if, as a result of your compiling your source code, portions
- of this Software are embedded into an Object form of such source code, you
- may redistribute such embedded portions in such Object form without complying
- with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
-
- In addition, if you combine or link compiled forms of this Software with
- software that is licensed under the GPLv2 ("Combined Software") and if a
- court of competent jurisdiction determines that the patent provision (Section
- 3), the indemnity provision (Section 9) or other Section of the License
- conflicts with the conditions of the GPLv2, you may retroactively and
- prospectively choose to deem waived or otherwise exclude such Section(s) of
- the License, but only in their entirety and only with respect to the Combined
- Software.
-
- ==============================================================================
diff --git a/LICENSE b/LICENSE
index af4b965..5311a0f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright © 2018-2024 GrapheneOS
+Copyright © 2018-2023 GrapheneOS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 6a1a91b..b3f820f 100644
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ there will be custom integration offering better performance in the future
along with other hardening for the C standard library implementation.
For Android, only the current generation, actively developed maintenance branch of the Android
-Open Source Project will be supported, which currently means `android15-release`.
+Open Source Project will be supported, which currently means `android13-qpr2-release`.
## Testing
@@ -159,9 +159,6 @@ line to the `/etc/ld.so.preload` configuration file:
The format of this configuration file is a whitespace-separated list, so it's
good practice to put each library on a separate line.
-On Debian systems `libhardened_malloc.so` should be installed into `/usr/lib/`
-to avoid preload failures caused by AppArmor profile restrictions.
-
Using the `LD_PRELOAD` environment variable to load it on a case-by-case basis
will not work when `AT_SECURE` is set such as with setuid binaries. It's also
generally not a recommended approach for production usage. The recommendation
@@ -473,16 +470,16 @@ was a bit less important and if a core goal was finding latent bugs.
* Errors other than ENOMEM from mmap, munmap, mprotect and mremap treated
as fatal, which can help to detect memory management gone wrong elsewhere
in the process.
-* Memory tagging for slab allocations via MTE on ARMv8.5+
+* [future] Memory tagging for slab allocations via MTE on ARMv8.5+
* random memory tags as the baseline, providing probabilistic protection
against various forms of memory corruption
* dedicated tag for free slots, set on free, for deterministic protection
against accessing freed memory
+ * store previous random tag within freed slab allocations, and increment it
+ to get the next tag for that slot to provide deterministic use-after-free
+ detection through multiple cycles of memory reuse
* guarantee distinct tags for adjacent memory allocations by incrementing
past matching values for deterministic detection of linear overflows
- * [future] store previous random tag and increment it to get the next tag
- for that slot to provide deterministic use-after-free detection through
- multiple cycles of memory reuse
## Randomness
@@ -724,46 +721,77 @@ freeing as there would be if the kernel supported these features directly.
## Memory tagging
-Random tags are set for all slab allocations when allocated, with 4 excluded values:
+Integrating extensive support for ARMv8.5 memory tagging is planned and this
+section will be expanded to cover the details on the chosen design. The approach
+for slab allocations is currently covered, but it can also be used for the
+allocator metadata region and large allocations.
-1. the reserved `0` tag
-2. the previous tag used for the slot
-3. the current (or previous) tag used for the slot to the left
-4. the current (or previous) tag used for the slot to the right
+Memory allocations are already always multiples of naturally aligned 16 byte
+units, so memory tags are a natural fit into a malloc implementation due to the
+16 byte alignment requirement. The only extra memory consumption will come from
+the hardware supported storage for the tag values (4 bits per 16 bytes).
-When a slab allocation is freed, the reserved `0` tag is set for the slot.
-Slab allocation slots are cleared before reuse when memory tagging is enabled.
+The baseline policy will be to generate random tags for each slab allocation
+slot on first use. The highest value will be reserved for marking freed memory
+allocations to detect any accesses to freed memory so it won't be part of the
+generated range. Adjacent slots will be guaranteed to have distinct memory tags
+in order to guarantee that linear overflows are detected. There are a few ways
+of implementing this and it will end up depending on the performance costs of
+different approaches. If there's an efficient way to fetch the adjacent tag
+values without wasting extra memory, it will be possible to check for them and
+skip them either by generating a new random value in a loop or incrementing
+past them since the tiny bit of bias wouldn't matter. Another approach would be
+alternating odd and even tag values but that would substantially reduce the
+overall randomness of the tags and there's very little entropy from the start.
-This ensures the following properties:
+Once a slab allocation has been freed, the tag will be set to the reserved
+value for free memory and the previous tag value will be stored inside the
+allocation itself. The next time the slot is allocated, the chosen tag value
+will be the previous value incremented by one to provide use-after-free
+detection between generations of allocations. The stored tag will be wiped
+before retagging the memory, to avoid leaking it and as part of preserving the
+security property of newly allocated memory being zeroed due to zero-on-free.
+It will eventually wrap all the way around, but this ends up providing a strong
+guarantee for many allocation cycles due to the combination of 4 bit tags with
+the FIFO quarantine feature providing delayed free. It also benefits from
+random slot allocation and the randomized portion of delayed free, which result
+in a further delay along with preventing a deterministic bypass by forcing a
+reuse after a certain number of allocation cycles. Similarly to the initial tag
+generation, tag values for adjacent allocations will be skipped by incrementing
+past them.
-- Linear overflows are deterministically detected.
-- Use-after-free are deterministically detected until the freed slot goes through
- both the random and FIFO quarantines, gets allocated again, goes through both
- quarantines again and then finally gets allocated again for a 2nd time.
-- Since the default `0` tag is reserved, untagged pointers can't access slab
- allocations and vice versa.
+For example, consider this slab of allocations that are not yet used with 15
+representing the tag for free memory. For the sake of simplicity, there will be
+no quarantine or other slabs for this example:
-Slab allocations are done in a statically reserved region for each size class
-and all metadata is in a statically reserved region, so interactions between
-different uses of the same address space is not applicable.
+ | 15 | 15 | 15 | 15 | 15 | 15 |
-Large allocations beyond the largest slab allocation size class (128k by
-default) are guaranteed to have randomly sized guard regions to the left and
-right. Random and FIFO address space quarantines provide use-after-free
-detection. We need to test whether the cost of random tags is acceptable to enabled them by default,
-since they would be useful for:
+Three slots are randomly chosen for allocations, with random tags assigned (2,
+7, 14) since these slots haven't ever been used and don't have saved values:
-- probabilistic detection of overflows
-- probabilistic detection of use-after-free once the address space is
- out of the quarantine and reused for another allocation
-- deterministic detection of use-after-free for reuse by another allocator.
+ | 15 | 2 | 15 | 7 | 14 | 15 |
-When memory tagging is enabled, checking for write-after-free at allocation
-time and checking canaries are both disabled. Canaries will be more thoroughly
-disabled when using memory tagging in the future, but Android currently has
-[very dynamic memory tagging support](https://source.android.com/docs/security/test/memory-safety/arm-mte)
-where it can be disabled at any time which creates a barrier to optimizing
-by disabling redundant features.
+The 2nd allocation slot is freed, and is set back to the tag for free memory
+(15), but with the previous tag value stored in the freed space:
+
+ | 15 | 15 | 15 | 7 | 14 | 15 |
+
+The first slot is allocated for the first time, receiving the random value 3:
+
+ | 3 | 15 | 15 | 7 | 14 | 15 |
+
+The 2nd slot is randomly chosen again, so the previous tag (2) is retrieved and
+incremented to 3 as part of the use-after-free mitigation. An adjacent
+allocation already uses the tag 3, so the tag is further incremented to 4 (it
+would be incremented to 5 if one of the adjacent tags was 4):
+
+ | 3 | 4 | 15 | 7 | 14 | 15 |
+
+The last slot is randomly chosen for the next allocation, and is assigned the
+random value 14. However, it's placed next to an allocation with the tag 14 so
+the tag is incremented and wraps around to 0:
+
+ | 3 | 4 | 15 | 7 | 14 | 0 |
## API extensions
diff --git a/androidtest/Android.bp b/androidtest/Android.bp
deleted file mode 100644
index ae0aa49..0000000
--- a/androidtest/Android.bp
+++ /dev/null
@@ -1,25 +0,0 @@
-java_test_host {
- name: "HMallocTest",
- srcs: [
- "src/**/*.java",
- ],
-
- libs: [
- "tradefed",
- "compatibility-tradefed",
- "compatibility-host-util",
- ],
-
- static_libs: [
- "cts-host-utils",
- "frameworks-base-hostutils",
- ],
-
- test_suites: [
- "general-tests",
- ],
-
- data_device_bins_64: [
- "memtag_test",
- ],
-}
diff --git a/androidtest/AndroidTest.xml b/androidtest/AndroidTest.xml
deleted file mode 100644
index 333f1dd..0000000
--- a/androidtest/AndroidTest.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/androidtest/memtag/Android.bp b/androidtest/memtag/Android.bp
deleted file mode 100644
index 75287f6..0000000
--- a/androidtest/memtag/Android.bp
+++ /dev/null
@@ -1,17 +0,0 @@
-cc_test {
- name: "memtag_test",
- srcs: ["memtag_test.cc"],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- "-O0",
- "-march=armv9-a+memtag",
- ],
-
- compile_multilib: "64",
-
- sanitize: {
- memtag_heap: true,
- },
-}
diff --git a/androidtest/memtag/memtag_test.cc b/androidtest/memtag/memtag_test.cc
deleted file mode 100644
index f858292..0000000
--- a/androidtest/memtag/memtag_test.cc
+++ /dev/null
@@ -1,351 +0,0 @@
-// needed to uncondionally enable assertions
-#undef NDEBUG
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include