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

Commit 1d1bb0d9 authored by Christian Wailes's avatar Christian Wailes Committed by Android (Google) Code Review
Browse files

Merge changes I5dfb6777,I82d734c5,I6e9aaad5,I80fb3b37

* changes:
  Replaces custom code with a library function.
  Moved and renamed DisableExecuteOnly to match file structure.
  Cleanup of the Zygote.java file.
  Fix FD leak in the Zygote.
parents c0dc4156 ee1fd45a
Loading
Loading
Loading
Loading
+39 −21
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ public final class Zygote {
     * Bit shift for use with {@link #API_ENFORCEMENT_POLICY_MASK}.
     *
     * (flags & API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT gives
     * @ApplicationInfo.ApiEnforcementPolicy values.
     * {@link ApplicationInfo.HiddenApiEnforcementPolicy} values.
     */
    public static final int API_ENFORCEMENT_POLICY_SHIFT =
            Integer.numberOfTrailingZeros(API_ENFORCEMENT_POLICY_MASK);
@@ -128,7 +128,7 @@ public final class Zygote {
    public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;

    /** Number of bytes sent to the Zygote over USAP pipes or the pool event FD */
    public static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;
    static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;

    /**
     * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
@@ -173,7 +173,7 @@ public final class Zygote {
    public static final int SOCKET_BUFFER_SIZE = 256;

    /** a prototype instance for a future List.toArray() */
    protected static final int[][] INT_ARRAY_2D = new int[0][0];
    static final int[][] INT_ARRAY_2D = new int[0][0];

    /**
     * @hide for internal use only.
@@ -231,7 +231,7 @@ public final class Zygote {
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
    static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            String packageName, String[] packagesForUID, String sandboxId, int targetSdkVersion) {
@@ -281,7 +281,7 @@ public final class Zygote {
     * @param instructionSet null-ok  The instruction set to use.
     * @param appDataDir null-ok  The data directory of the app.
     */
    public static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
    private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName,
            boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
            String[] packagesForUID, String sandboxId) {
@@ -337,7 +337,7 @@ public final class Zygote {
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
    static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();
        // Resets nice priority for zygote process.
@@ -367,7 +367,7 @@ public final class Zygote {
     *
     * @param appInfo ApplicationInfo of the application
     */
    protected static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
    static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
        for (String path : appInfo.getAllApkPaths()) {
            Zygote.nativeAllowFileAcrossFork(path);
        }
@@ -413,7 +413,7 @@ public final class Zygote {
                defaultValue);
    }

    protected static void emptyUsapPool() {
    static void emptyUsapPool() {
        nativeEmptyUsapPool();
    }

@@ -425,7 +425,7 @@ public final class Zygote {
     * Note that Device Config is not available without an application so SystemProperties is used
     * instead.
     *
     * @see SystemProperties.getBoolean
     * @see SystemProperties#getBoolean
     *
     * TODO (chriswailes): Cache the system property location in native code and then write a JNI
     *                     function to fetch it.
@@ -566,7 +566,19 @@ public final class Zygote {
            System.exit(-1);
        } finally {
            IoUtils.closeQuietly(sessionSocket);
            IoUtils.closeQuietly(usapPoolSocket);

            try {
                // This socket is closed using Os.close due to an issue with the implementation of
                // LocalSocketImp.close.  Because the raw FD is created by init and then loaded from
                // an environment variable (as opposed to being created by the LocalSocketImpl
                // itself) the current implementation will not actually close the underlying FD.
                //
                // See b/130309968 for discussion of this issue.
                Os.close(usapPoolSocket.getFileDescriptor());
            } catch (ErrnoException ex) {
                Log.e("USAP", "Failed to close USAP pool socket");
                throw new RuntimeException(ex);
            }
        }

        try {
@@ -651,7 +663,7 @@ public final class Zygote {
    /**
     * Mark execute-only segments of libraries read+execute for apps with targetSdkVersion<Q.
     */
    protected static void disableExecuteOnly(int targetSdkVersion) {
    private static void disableExecuteOnly(int targetSdkVersion) {
        if ((targetSdkVersion < Build.VERSION_CODES.Q) && !nativeDisableExecuteOnly()) {
            Log.e("Zygote", "Failed to set libraries to read+execute.");
        }
@@ -662,7 +674,7 @@ public final class Zygote {
    /**
     * @return  Raw file descriptors for the read-end of USAP reporting pipes.
     */
    protected static int[] getUsapPipeFDs() {
    static int[] getUsapPipeFDs() {
        return nativeGetUsapPipeFDs();
    }

@@ -674,7 +686,7 @@ public final class Zygote {
     * @param usapPID  Process ID of the entry to remove
     * @return True if the entry was removed; false if it doesn't exist
     */
    protected static boolean removeUsapTableEntry(int usapPID) {
    static boolean removeUsapTableEntry(int usapPID) {
        return nativeRemoveUsapTableEntry(usapPID);
    }

@@ -687,9 +699,10 @@ public final class Zygote {
     *
     * @param args non-null; zygote spawner arguments
     * @param peer non-null; peer credentials
     * @throws ZygoteSecurityException
     * @throws ZygoteSecurityException Indicates a security issue when applying the UID based
     *  security policies
     */
    protected static void applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)
    static void applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)
            throws ZygoteSecurityException {

        if (peer.getUid() == Process.SYSTEM_UID) {
@@ -725,7 +738,7 @@ public final class Zygote {
     *
     * @param args non-null; zygote spawner args
     */
    protected static void applyDebuggerSystemProperty(ZygoteArguments args) {
    static void applyDebuggerSystemProperty(ZygoteArguments args) {
        if (RoSystemProperties.DEBUGGABLE) {
            args.mRuntimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
        }
@@ -742,9 +755,10 @@ public final class Zygote {
     *
     * @param args non-null; zygote spawner arguments
     * @param peer non-null; peer credentials
     * @throws ZygoteSecurityException
     * @throws ZygoteSecurityException Thrown when `--invoke-with` is specified for a non-debuggable
     *  application.
     */
    protected static void applyInvokeWithSecurityPolicy(ZygoteArguments args, Credentials peer)
    static void applyInvokeWithSecurityPolicy(ZygoteArguments args, Credentials peer)
            throws ZygoteSecurityException {
        int peerUid = peer.getUid();

@@ -761,7 +775,7 @@ public final class Zygote {
     *
     * @param args non-null; zygote args
     */
    protected static void applyInvokeWithSystemProperty(ZygoteArguments args) {
    static void applyInvokeWithSystemProperty(ZygoteArguments args) {
        if (args.mInvokeWith == null && args.mNiceName != null) {
            String property = "wrap." + args.mNiceName;
            args.mInvokeWith = SystemProperties.get(property);
@@ -839,11 +853,15 @@ public final class Zygote {
        }
    }

    // This function is called from native code in com_android_internal_os_Zygote.cpp
    @SuppressWarnings("unused")
    private static void callPostForkSystemServerHooks() {
        // SystemServer specific post fork hooks run before child post fork hooks.
        ZygoteHooks.postForkSystemServer();
    }

    // This function is called from native code in com_android_internal_os_Zygote.cpp
    @SuppressWarnings("unused")
    private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
            boolean isZygote, String instructionSet) {
        ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
@@ -865,7 +883,7 @@ public final class Zygote {
     *
     * @param command The shell command to execute.
     */
    public static void execShell(String command) {
    static void execShell(String command) {
        String[] args = { "/system/bin/sh", "-c", command };
        try {
            Os.execv(args[0], args);
@@ -883,7 +901,7 @@ public final class Zygote {
     * @param args An array of argument strings to be quoted and appended to the command.
     * @see #execShell(String)
     */
    public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
    static void appendQuotedShellArgs(StringBuilder command, String[] args) {
        for (String arg : args) {
            command.append(" '").append(arg.replace("'", "'\\''")).append("'");
        }
+22 −31
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@
#include <cutils/ashmem.h>
#include <cutils/fs.h>
#include <cutils/multiuser.h>
#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
#include <utils/String8.h>
#include <utils/Trace.h>
@@ -135,13 +136,6 @@ static bool gIsSecurityEnforced = true;
 */
static constexpr size_t MAX_NAME_LENGTH = 15;

/**
 * The prefix string for environmental variables storing socket FDs created by
 * init.
 */

static constexpr std::string_view ANDROID_SOCKET_PREFIX("ANDROID_SOCKET_");

/**
 * The file descriptor for the Zygote socket opened by init.
 */
@@ -1665,6 +1659,20 @@ static void UnmountStorageOnInit(JNIEnv* env) {
  UnmountTree("/storage");
}

static int DisableExecuteOnly(struct dl_phdr_info* info,
                              size_t size [[maybe_unused]],
                              void* data [[maybe_unused]]) {
  // Search for any execute-only segments and mark them read+execute.
  for (int i = 0; i < info->dlpi_phnum; i++) {
    if ((info->dlpi_phdr[i].p_type == PT_LOAD) && (info->dlpi_phdr[i].p_flags == PF_X)) {
      mprotect(reinterpret_cast<void*>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr),
               info->dlpi_phdr[i].p_memsz, PROT_READ | PROT_EXEC);
    }
  }
  // Return non-zero to exit dl_iterate_phdr.
  return 0;
}

}  // anonymous namespace

namespace android {
@@ -1882,22 +1890,17 @@ static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jc
   * Obtain file descriptors created by init from the environment.
   */

  std::string android_socket_prefix(ANDROID_SOCKET_PREFIX);
  std::string env_var_name = android_socket_prefix + (is_primary ? "zygote" : "zygote_secondary");
  char* env_var_val = getenv(env_var_name.c_str());

  if (env_var_val != nullptr) {
    gZygoteSocketFD = atoi(env_var_val);
  gZygoteSocketFD =
      android_get_control_socket(is_primary ? "zygote" : "zygote_secondary");
  if (gZygoteSocketFD >= 0) {
    ALOGV("Zygote:zygoteSocketFD = %d", gZygoteSocketFD);
  } else {
    ALOGE("Unable to fetch Zygote socket file descriptor");
  }

  env_var_name = android_socket_prefix + (is_primary ? "usap_pool_primary" : "usap_pool_secondary");
  env_var_val = getenv(env_var_name.c_str());

  if (env_var_val != nullptr) {
    gUsapPoolSocketFD = atoi(env_var_val);
  gUsapPoolSocketFD =
      android_get_control_socket(is_primary ? "usap_pool_primary" : "usap_pool_secondary");
  if (gUsapPoolSocketFD >= 0) {
    ALOGV("Zygote:usapPoolSocketFD = %d", gUsapPoolSocketFD);
  } else {
    ALOGE("Unable to fetch USAP pool socket file descriptor");
@@ -2006,24 +2009,12 @@ static void com_android_internal_os_Zygote_nativeEmptyUsapPool(JNIEnv* env, jcla
  }
}

static int disable_execute_only(struct dl_phdr_info *info, size_t size, void *data) {
  // Search for any execute-only segments and mark them read+execute.
  for (int i = 0; i < info->dlpi_phnum; i++) {
    if ((info->dlpi_phdr[i].p_type == PT_LOAD) && (info->dlpi_phdr[i].p_flags == PF_X)) {
      mprotect(reinterpret_cast<void*>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr),
              info->dlpi_phdr[i].p_memsz, PROT_READ | PROT_EXEC);
    }
  }
  // Return non-zero to exit dl_iterate_phdr.
  return 0;
}

/**
 * @param env  Managed runtime environment
 * @return  True if disable was successful.
 */
static jboolean com_android_internal_os_Zygote_nativeDisableExecuteOnly(JNIEnv* env, jclass) {
  return dl_iterate_phdr(disable_execute_only, nullptr) == 0;
  return dl_iterate_phdr(DisableExecuteOnly, nullptr) == 0;
}

static const JNINativeMethod gMethods[] = {