diff options
Diffstat (limited to 'core/java/android/os')
-rw-r--r-- | core/java/android/os/Build.java | 41 | ||||
-rw-r--r-- | core/java/android/os/INetworkManagementService.aidl | 3 | ||||
-rw-r--r-- | core/java/android/os/Process.java | 21 | ||||
-rw-r--r-- | core/java/android/os/RecoverySystem.java | 41 |
4 files changed, 82 insertions, 24 deletions
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 862f4c4..2df9be2 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -23,7 +23,11 @@ import com.android.internal.telephony.TelephonyProperties; import dalvik.system.VMRuntime; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Information about the current build, extracted from system properties. @@ -664,6 +668,7 @@ public class Build { /** The type of build, like "user" or "eng". */ public static final String TYPE = getString("ro.build.type"); + private static String TYPE_FOR_APPS = parseBuildTypeFromFingerprint(); /** Comma-separated tags describing the build, like "unsigned,debug". */ public static final String TAGS = getString("ro.build.tags"); @@ -690,6 +695,42 @@ public class Build { return finger; } + // Some apps like to compare the build type embedded in fingerprint + // to the actual build type. As the fingerprint in our case is almost + // always hardcoded to the stock ROM fingerprint, provide that instead + // of the actual one if possible. + private static String parseBuildTypeFromFingerprint() { + final String fingerprint = SystemProperties.get("ro.build.fingerprint"); + if (TextUtils.isEmpty(fingerprint)) { + return null; + } + Pattern fingerprintPattern = + Pattern.compile("(.*)\\/(.*)\\/(.*):(.*)\\/(.*)\\/(.*):(.*)\\/(.*)"); + Matcher matcher = fingerprintPattern.matcher(fingerprint); + return matcher.matches() ? matcher.group(7) : null; + } + + /** @hide */ + public static void adjustBuildTypeIfNeeded() { + if (UserHandle.isApp(Process.myUid()) && !TextUtils.isEmpty(TYPE_FOR_APPS)) { + try { + // This is sick. TYPE is final (which can't be changed because it's an API + // guarantee), but we have to reassign it. Resort to reflection to unset the + // final modifier, change the value and restore the final modifier afterwards. + Field typeField = Build.class.getField("TYPE"); + Field accessFlagsField = Field.class.getDeclaredField("accessFlags"); + accessFlagsField.setAccessible(true); + int currentFlags = accessFlagsField.getInt(typeField); + accessFlagsField.setInt(typeField, currentFlags & ~Modifier.FINAL); + typeField.set(null, TYPE_FOR_APPS); + accessFlagsField.setInt(typeField, currentFlags); + accessFlagsField.setAccessible(false); + } catch (Exception e) { + // shouldn't happen, but we don't want to crash the app even if it does happen + } + } + } + /** * Ensure that raw fingerprint system property is defined. If it was derived * dynamically by {@link #deriveFingerprint()} this is where we push the diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index cd84c8f..aa3921a 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -440,4 +440,7 @@ interface INetworkManagementService void addInterfaceToLocalNetwork(String iface, in List<RouteInfo> routes); void removeInterfaceFromLocalNetwork(String iface); + + void restrictAppOnData(int uid, boolean restrict); + void restrictAppOnWlan(int uid, boolean restrict); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 65b09eb..02466cc 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -539,6 +539,15 @@ public class Process { ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { try { + // Throw early if any of the arguments are malformed. This means we can + // avoid writing a partial response to the zygote. + int sz = args.size(); + for (int i = 0; i < sz; i++) { + if (args.get(i).indexOf('\n') >= 0) { + throw new ZygoteStartFailedEx("embedded newlines not allowed"); + } + } + /** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: @@ -555,13 +564,8 @@ public class Process { writer.write(Integer.toString(args.size())); writer.newLine(); - int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); - if (arg.indexOf('\n') >= 0) { - throw new ZygoteStartFailedEx( - "embedded newlines not allowed"); - } writer.write(arg); writer.newLine(); } @@ -570,11 +574,16 @@ public class Process { // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); + + // Always read the entire result from the input stream to avoid leaving + // bytes in the stream for future process starts to accidentally stumble + // upon. result.pid = inputStream.readInt(); + result.usingWrapper = inputStream.readBoolean(); + if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } - result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 4b6e6c1..d277e65 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -335,22 +335,27 @@ public class RecoverySystem { throws IOException { String filename = packageFile.getCanonicalPath(); - FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE); - try { - uncryptFile.write(filename + "\n"); - } finally { - uncryptFile.close(); - } - // UNCRYPT_FILE needs to be readable by system server on bootup. - if (!UNCRYPT_FILE.setReadable(true, false)) { - Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath()); - } - Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!"); + final String cryptoStatus = SystemProperties.get("ro.crypto.state", "unsupported"); + final boolean isEncrypted = "encrypted".equalsIgnoreCase(cryptoStatus); - // If the package is on the /data partition, write the block map file - // into COMMAND_FILE instead. - if (filename.startsWith("/data/")) { - filename = "@/cache/recovery/block.map"; + if (isEncrypted) { + FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE); + try { + uncryptFile.write(filename + "\n"); + } finally { + uncryptFile.close(); + } + // UNCRYPT_FILE needs to be readable by system server on bootup. + if (!UNCRYPT_FILE.setReadable(true, false)) { + Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath()); + } + Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!"); + + // If the package is on the /data partition, write the block map file + // into COMMAND_FILE instead. + if (filename.startsWith("/data/")) { + filename = "@/cache/recovery/block.map"; + } } final String filenameArg = "--update_package=" + filename; @@ -372,18 +377,18 @@ public class RecoverySystem { * @throws SecurityException if the current user is not allowed to wipe data. */ public static void rebootWipeUserData(Context context) throws IOException { - rebootWipeUserData(context, false, context.getPackageName(), false); + rebootWipeUserData(context, false, context.getPackageName(), true); } /** {@hide} */ public static void rebootWipeUserData(Context context, String reason) throws IOException { - rebootWipeUserData(context, false, reason, false); + rebootWipeUserData(context, false, reason, true); } /** {@hide} */ public static void rebootWipeUserData(Context context, boolean shutdown) throws IOException { - rebootWipeUserData(context, shutdown, context.getPackageName(), false); + rebootWipeUserData(context, shutdown, context.getPackageName(), true); } /** |