am 5c8e1a6e: Merge "Allow PMS to restorecon directories under /data."
* commit '5c8e1a6ed4b7e12632c7c82b94e1909ae82b0706': Allow PMS to restorecon directories under /data.
This commit is contained in:
@@ -396,4 +396,8 @@ public final class Installer {
|
||||
|
||||
return execute(builder.toString());
|
||||
}
|
||||
|
||||
public boolean restoreconData() {
|
||||
return (execute("restorecondata") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user