Loading services/java/com/android/server/pm/Installer.java +4 −0 Original line number Diff line number Diff line Loading @@ -396,4 +396,8 @@ public final class Installer { return execute(builder.toString()); } public boolean restoreconData() { return (execute("restorecondata") == 0); } } services/java/com/android/server/pm/PackageManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -1486,6 +1486,13 @@ public class PackageManagerService extends IPackageManager.Stub { // can downgrade to reader mSettings.writeLPr(); if (SELinuxMMAC.shouldRestorecon()) { Slog.i(TAG, "Relabeling of /data/data and /data/user issued."); if (mInstaller.restoreconData()) { SELinuxMMAC.setRestoreconDone(); } } EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); Loading services/java/com/android/server/pm/SELinuxMMAC.java +97 −0 Original line number Diff line number Diff line Loading @@ -25,11 +25,16 @@ import android.util.Xml; import com.android.internal.util.XmlUtils; import libcore.io.IoUtils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; Loading Loading @@ -60,6 +65,13 @@ public final class SELinuxMMAC { new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"), null}; // Location of seapp_contexts policy file. private static final String SEAPP_CONTEXTS_FILE = "/seapp_contexts"; // Stores the hash of the last used seapp_contexts file. private static final String SEAPP_HASH_FILE = Environment.getDataDirectory().toString() + "/system/seapp_hash"; // Signature policy stanzas static class Policy { private String seinfo; Loading Loading @@ -391,4 +403,89 @@ public final class SELinuxMMAC { return (sDefaultSeinfo != null); } /** * Determines if a recursive restorecon on /data/data and /data/user is needed. * It does this by comparing the SHA-1 of the seapp_contexts file against the * stored hash at /data/system/seapp_hash. * * @return Returns true if the restorecon should occur or false otherwise. */ public static boolean shouldRestorecon() { // Any error with the seapp_contexts file should be fatal byte[] currentHash = null; try { currentHash = returnHash(SEAPP_CONTEXTS_FILE); } catch (IOException ioe) { Slog.e(TAG, "Error with hashing seapp_contexts.", ioe); return false; } // Push past any error with the stored hash file byte[] storedHash = null; try { storedHash = IoUtils.readFileAsByteArray(SEAPP_HASH_FILE); } catch (IOException ioe) { Slog.e(TAG, "Error opening " + SEAPP_HASH_FILE + ". Assuming first boot.", ioe); } return (storedHash == null || !MessageDigest.isEqual(storedHash, currentHash)); } /** * Stores the SHA-1 of the seapp_contexts to /data/system/seapp_hash. */ public static void setRestoreconDone() { try { final byte[] currentHash = returnHash(SEAPP_CONTEXTS_FILE); dumpHash(new File(SEAPP_HASH_FILE), currentHash); } catch (IOException ioe) { Slog.e(TAG, "Error with saving hash to " + SEAPP_HASH_FILE, ioe); } } /** * Dump the contents of a byte array to a specified file. * * @param file The file that receives the byte array content. * @param content A byte array that will be written to the specified file. * @throws IOException if any failed I/O operation occured. * Included is the failure to atomically rename the tmp * file used in the process. */ private static void dumpHash(File file, byte[] content) throws IOException { FileOutputStream fos = null; File tmp = null; try { tmp = File.createTempFile("seapp_hash", ".journal", file.getParentFile()); tmp.setReadable(true); fos = new FileOutputStream(tmp); fos.write(content); fos.getFD().sync(); if (!tmp.renameTo(file)) { throw new IOException("Failure renaming " + file.getCanonicalPath()); } } finally { if (tmp != null) { tmp.delete(); } IoUtils.closeQuietly(fos); } } /** * Return the SHA-1 of a file. * * @param file The path to the file given as a string. * @return Returns the SHA-1 of the file as a byte array. * @throws IOException if any failed I/O operations occured. */ private static byte[] returnHash(String file) throws IOException { try { final byte[] contents = IoUtils.readFileAsByteArray(file); return MessageDigest.getInstance("SHA-1").digest(contents); } catch (NoSuchAlgorithmException nsae) { throw new RuntimeException(nsae); // impossible } } } Loading
services/java/com/android/server/pm/Installer.java +4 −0 Original line number Diff line number Diff line Loading @@ -396,4 +396,8 @@ public final class Installer { return execute(builder.toString()); } public boolean restoreconData() { return (execute("restorecondata") == 0); } }
services/java/com/android/server/pm/PackageManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -1486,6 +1486,13 @@ public class PackageManagerService extends IPackageManager.Stub { // can downgrade to reader mSettings.writeLPr(); if (SELinuxMMAC.shouldRestorecon()) { Slog.i(TAG, "Relabeling of /data/data and /data/user issued."); if (mInstaller.restoreconData()) { SELinuxMMAC.setRestoreconDone(); } } EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); Loading
services/java/com/android/server/pm/SELinuxMMAC.java +97 −0 Original line number Diff line number Diff line Loading @@ -25,11 +25,16 @@ import android.util.Xml; import com.android.internal.util.XmlUtils; import libcore.io.IoUtils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; Loading Loading @@ -60,6 +65,13 @@ public final class SELinuxMMAC { new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"), null}; // Location of seapp_contexts policy file. private static final String SEAPP_CONTEXTS_FILE = "/seapp_contexts"; // Stores the hash of the last used seapp_contexts file. private static final String SEAPP_HASH_FILE = Environment.getDataDirectory().toString() + "/system/seapp_hash"; // Signature policy stanzas static class Policy { private String seinfo; Loading Loading @@ -391,4 +403,89 @@ public final class SELinuxMMAC { return (sDefaultSeinfo != null); } /** * Determines if a recursive restorecon on /data/data and /data/user is needed. * It does this by comparing the SHA-1 of the seapp_contexts file against the * stored hash at /data/system/seapp_hash. * * @return Returns true if the restorecon should occur or false otherwise. */ public static boolean shouldRestorecon() { // Any error with the seapp_contexts file should be fatal byte[] currentHash = null; try { currentHash = returnHash(SEAPP_CONTEXTS_FILE); } catch (IOException ioe) { Slog.e(TAG, "Error with hashing seapp_contexts.", ioe); return false; } // Push past any error with the stored hash file byte[] storedHash = null; try { storedHash = IoUtils.readFileAsByteArray(SEAPP_HASH_FILE); } catch (IOException ioe) { Slog.e(TAG, "Error opening " + SEAPP_HASH_FILE + ". Assuming first boot.", ioe); } return (storedHash == null || !MessageDigest.isEqual(storedHash, currentHash)); } /** * Stores the SHA-1 of the seapp_contexts to /data/system/seapp_hash. */ public static void setRestoreconDone() { try { final byte[] currentHash = returnHash(SEAPP_CONTEXTS_FILE); dumpHash(new File(SEAPP_HASH_FILE), currentHash); } catch (IOException ioe) { Slog.e(TAG, "Error with saving hash to " + SEAPP_HASH_FILE, ioe); } } /** * Dump the contents of a byte array to a specified file. * * @param file The file that receives the byte array content. * @param content A byte array that will be written to the specified file. * @throws IOException if any failed I/O operation occured. * Included is the failure to atomically rename the tmp * file used in the process. */ private static void dumpHash(File file, byte[] content) throws IOException { FileOutputStream fos = null; File tmp = null; try { tmp = File.createTempFile("seapp_hash", ".journal", file.getParentFile()); tmp.setReadable(true); fos = new FileOutputStream(tmp); fos.write(content); fos.getFD().sync(); if (!tmp.renameTo(file)) { throw new IOException("Failure renaming " + file.getCanonicalPath()); } } finally { if (tmp != null) { tmp.delete(); } IoUtils.closeQuietly(fos); } } /** * Return the SHA-1 of a file. * * @param file The path to the file given as a string. * @return Returns the SHA-1 of the file as a byte array. * @throws IOException if any failed I/O operations occured. */ private static byte[] returnHash(String file) throws IOException { try { final byte[] contents = IoUtils.readFileAsByteArray(file); return MessageDigest.getInstance("SHA-1").digest(contents); } catch (NoSuchAlgorithmException nsae) { throw new RuntimeException(nsae); // impossible } } }