Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1a6917c authored by Peter Collingbourne's avatar Peter Collingbourne
Browse files

Implement initial policy for memory tag checks.

System apps and the system_server receive async tag checks, while all other
app processes have it disabled. Developers may enable async tag checks
per application with:

$ adb shell am compat 135772972 <app.name>

Bug: 135772972
Change-Id: I154623941eec8e79af347453fbca1b062346c85b
parent f057f5d8
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -1054,4 +1054,9 @@ public final class Zygote {
     */
     */
    @FastNative
    @FastNative
    public static native int nativeParseSigChld(byte[] in, int length, int[] out);
    public static native int nativeParseSigChld(byte[] in, int length, int[] out);

    /**
     * Returns whether the hardware supports memory tagging (ARM MTE).
     */
    public static native boolean nativeSupportsMemoryTagging();
}
}
+9 −3
Original line number Original line Diff line number Diff line
@@ -783,9 +783,15 @@ public class ZygoteInit {
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);


            /* Enable pointer tagging in the system server unconditionally. Hardware support for
            if (Zygote.nativeSupportsMemoryTagging()) {
             * this is present in all ARMv8 CPUs; this flag has no effect on other platforms. */
                /* The system server is more privileged than regular app processes, so it has async
                 * tag checks enabled on hardware that supports memory tagging. */
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;
            } else {
                /* Enable pointer tagging in the system server. Hardware support for this is present
                 * in all ARMv8 CPUs; this flag has no effect on other platforms. */
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
            }


            if (shouldProfileSystemServer()) {
            if (shouldProfileSystemServer()) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
+6 −0
Original line number Original line Diff line number Diff line
@@ -307,4 +307,10 @@ cc_library_shared {
            enabled: true,
            enabled: true,
        },
        },
    },
    },

    product_variables: {
        experimental_mte: {
            cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
        },
    },
}
}
+53 −0
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@
#include <signal.h>
#include <signal.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/auxv.h>
#include <sys/capability.h>
#include <sys/capability.h>
#include <sys/cdefs.h>
#include <sys/cdefs.h>
#include <sys/eventfd.h>
#include <sys/eventfd.h>
@@ -76,6 +77,8 @@
#include <android-base/stringprintf.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <android-base/unique_fd.h>
#include <bionic/malloc.h>
#include <bionic/malloc.h>
#include <bionic/mte.h>
#include <bionic/mte_kernel.h>
#include <cutils/fs.h>
#include <cutils/fs.h>
#include <cutils/multiuser.h>
#include <cutils/multiuser.h>
#include <cutils/sockets.h>
#include <cutils/sockets.h>
@@ -355,6 +358,8 @@ enum RuntimeFlags : uint32_t {
    PROFILE_FROM_SHELL = 1 << 15,
    PROFILE_FROM_SHELL = 1 << 15,
    MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20),
    MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20),
    MEMORY_TAG_LEVEL_TBI = 1 << 19,
    MEMORY_TAG_LEVEL_TBI = 1 << 19,
    MEMORY_TAG_LEVEL_ASYNC = 2 << 19,
    MEMORY_TAG_LEVEL_SYNC = 3 << 19,
    GWP_ASAN_LEVEL_MASK = (1 << 21) | (1 << 22),
    GWP_ASAN_LEVEL_MASK = (1 << 21) | (1 << 22),
    GWP_ASAN_LEVEL_NEVER = 0 << 21,
    GWP_ASAN_LEVEL_NEVER = 0 << 21,
    GWP_ASAN_LEVEL_LOTTERY = 1 << 21,
    GWP_ASAN_LEVEL_LOTTERY = 1 << 21,
@@ -1593,6 +1598,28 @@ static void BindMountStorageDirs(JNIEnv* env, jobjectArray pkg_data_info_list,
  }
  }
}
}


#ifdef ANDROID_EXPERIMENTAL_MTE
static void SetTagCheckingLevel(int level) {
#ifdef __aarch64__
  if (!(getauxval(AT_HWCAP2) & HWCAP2_MTE)) {
    return;
  }

  int tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
  if (tagged_addr_ctrl < 0) {
    ALOGE("prctl(PR_GET_TAGGED_ADDR_CTRL) failed: %s", strerror(errno));
    return;
  }

  tagged_addr_ctrl = (tagged_addr_ctrl & ~PR_MTE_TCF_MASK) | level;
  if (prctl(PR_SET_TAGGED_ADDR_CTRL, tagged_addr_ctrl, 0, 0, 0) < 0) {
    ALOGE("prctl(PR_SET_TAGGED_ADDR_CTRL, %d) failed: %s", tagged_addr_ctrl,
          strerror(errno));
  }
#endif
}
#endif

// Utility routine to specialize a zygote child process.
// Utility routine to specialize a zygote child process.
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
                             jint runtime_flags, jobjectArray rlimits,
                             jint runtime_flags, jobjectArray rlimits,
@@ -1725,7 +1752,23 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
    case RuntimeFlags::MEMORY_TAG_LEVEL_TBI:
    case RuntimeFlags::MEMORY_TAG_LEVEL_TBI:
      heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
      heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
      break;
      break;
    case RuntimeFlags::MEMORY_TAG_LEVEL_ASYNC:
#ifdef ANDROID_EXPERIMENTAL_MTE
      SetTagCheckingLevel(PR_MTE_TCF_ASYNC);
#endif
      heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC;
      break;
    case RuntimeFlags::MEMORY_TAG_LEVEL_SYNC:
#ifdef ANDROID_EXPERIMENTAL_MTE
      SetTagCheckingLevel(PR_MTE_TCF_SYNC);
#endif
      // TODO(pcc): Use SYNC here once the allocator supports it.
      heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC;
      break;
    default:
    default:
#ifdef ANDROID_EXPERIMENTAL_MTE
      SetTagCheckingLevel(PR_MTE_TCF_NONE);
#endif
      heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
      heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
  }
  }
  android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level));
  android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level));
@@ -2422,6 +2465,14 @@ static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclas
    return -1;
    return -1;
}
}


static jboolean com_android_internal_os_Zygote_nativeSupportsMemoryTagging(JNIEnv* env, jclass) {
#if defined(__aarch64__)
  return mte_supported();
#else
  return false;
#endif
}

static const JNINativeMethod gMethods[] = {
static const JNINativeMethod gMethods[] = {
        {"nativeForkAndSpecialize",
        {"nativeForkAndSpecialize",
         "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
         "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
@@ -2457,6 +2508,8 @@ static const JNINativeMethod gMethods[] = {
         (void*)com_android_internal_os_Zygote_nativeBoostUsapPriority},
         (void*)com_android_internal_os_Zygote_nativeBoostUsapPriority},
        {"nativeParseSigChld", "([BI[I)I",
        {"nativeParseSigChld", "([BI[I)I",
         (void*)com_android_internal_os_Zygote_nativeParseSigChld},
         (void*)com_android_internal_os_Zygote_nativeParseSigChld},
        {"nativeSupportsMemoryTagging", "()Z",
         (void*)com_android_internal_os_Zygote_nativeSupportsMemoryTagging},
};
};


int register_com_android_internal_os_Zygote(JNIEnv* env) {
int register_com_android_internal_os_Zygote(JNIEnv* env) {
+24 −5
Original line number Original line Diff line number Diff line
@@ -111,6 +111,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.Zygote;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.FrameworkStatsLog;
@@ -346,6 +347,14 @@ public final class ProcessList {
    @EnabledAfter(targetSdkVersion = VersionCodes.Q)
    @EnabledAfter(targetSdkVersion = VersionCodes.Q)
    private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.
    private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.


    /**
     * Enable memory tag checks in non-system apps. This flag will only have an effect on
     * hardware supporting the ARM Memory Tagging Extension (MTE).
     */
    @ChangeId
    @Disabled
    private static final long NATIVE_MEMORY_TAGGING = 135772972; // This is a bug id.

    /**
    /**
     * Enable sampled memory bug detection in the app.
     * Enable sampled memory bug detection in the app.
     * @see <a href="https://source.android.com/devices/tech/debug/gwp-asan">GWP-ASan</a>.
     * @see <a href="https://source.android.com/devices/tech/debug/gwp-asan">GWP-ASan</a>.
@@ -1828,12 +1837,22 @@ public final class ProcessList {
                runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
                runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
            }
            }


            // Enable heap pointer tagging, unless disabled by the app manifest, target sdk level,
            if (Zygote.nativeSupportsMemoryTagging()) {
            // or the compat feature.
                // System apps are generally more privileged than regular apps, and don't have the
                // same app compat concerns as regular apps, so we enable async tag checks for all
                // of their processes.
                if ((app.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0
                        || mPlatformCompat.isChangeEnabled(NATIVE_MEMORY_TAGGING, app.info)) {
                    runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;
                }
            } else {
                // Enable heap pointer tagging, unless disabled by the app manifest, target sdk
                // level, or the compat feature.
                if (app.info.allowsNativeHeapPointerTagging()
                if (app.info.allowsNativeHeapPointerTagging()
                        && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) {
                        && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) {
                    runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
                    runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
                }
                }
            }


            runtimeFlags |= decideGwpAsanLevel(app);
            runtimeFlags |= decideGwpAsanLevel(app);