* commit 'e75d340ae5919942d19f57856ae9e3f8bc62e098': Allow PMS to restorecon directories under /data.
This commit is contained in:
@@ -406,4 +406,8 @@ public final class Installer extends SystemService {
|
|||||||
|
|
||||||
return execute(builder.toString());
|
return execute(builder.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean restoreconData() {
|
||||||
|
return (execute("restorecondata") == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1493,6 +1493,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
|||||||
// can downgrade to reader
|
// can downgrade to reader
|
||||||
mSettings.writeLPr();
|
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,
|
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
|
||||||
SystemClock.uptimeMillis());
|
SystemClock.uptimeMillis());
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,16 @@ import android.util.Xml;
|
|||||||
|
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
|
|
||||||
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@@ -60,6 +65,13 @@ public final class SELinuxMMAC {
|
|||||||
new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"),
|
new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"),
|
||||||
null};
|
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
|
// Signature policy stanzas
|
||||||
static class Policy {
|
static class Policy {
|
||||||
private String seinfo;
|
private String seinfo;
|
||||||
@@ -391,4 +403,89 @@ public final class SELinuxMMAC {
|
|||||||
|
|
||||||
return (sDefaultSeinfo != null);
|
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