summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/BackupManagerService.java14
-rw-r--r--services/java/com/android/server/Watchdog.java9
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/java/com/android/server/pm/Installer.java8
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java21
-rw-r--r--services/java/com/android/server/pm/SELinuxMMAC.java294
-rw-r--r--services/java/com/android/server/pm/Settings.java3
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java6
8 files changed, 345 insertions, 12 deletions
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 7ac314b..b0561df 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -63,6 +63,7 @@ import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SELinux;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -743,6 +744,9 @@ class BackupManagerService extends IBackupManager.Stub {
// correct directory.
mBaseStateDir = new File(Environment.getSecureDataDirectory(), "backup");
mBaseStateDir.mkdirs();
+ if (!SELinux.restorecon(mBaseStateDir)) {
+ Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+ }
mDataDir = Environment.getDownloadCacheDirectory();
mPasswordHashFile = new File(mBaseStateDir, "pwhash");
@@ -2133,6 +2137,10 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
+ if (!SELinux.restorecon(mBackupDataName)) {
+ Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataName);
+ }
+
mNewState = ParcelFileDescriptor.open(mNewStateName,
ParcelFileDescriptor.MODE_READ_WRITE |
ParcelFileDescriptor.MODE_CREATE |
@@ -3795,7 +3803,7 @@ class BackupManagerService extends IBackupManager.Stub {
b.append(String.format(" %9d ", info.size));
Date stamp = new Date(info.mtime);
- b.append(new SimpleDateFormat("MMM dd kk:mm:ss ").format(stamp));
+ b.append(new SimpleDateFormat("MMM dd HH:mm:ss ").format(stamp));
b.append(info.packageName);
b.append(" :: ");
@@ -4572,6 +4580,10 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
+ if (!SELinux.restorecon(mBackupDataName)) {
+ Slog.e(TAG, "SElinux restorecon failed for " + mBackupDataName);
+ }
+
if (mTransport.getRestoreData(mBackupData) != BackupConstants.TRANSPORT_OK) {
// Transport-level failure, so we wind everything up and
// terminate the restore operation.
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index b2a8ad8..1663106 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -29,6 +29,7 @@ import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Debug;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.ServiceManager;
@@ -114,6 +115,10 @@ public class Watchdog extends Thread {
* Used for scheduling monitor callbacks and checking memory usage.
*/
final class HeartbeatHandler extends Handler {
+ HeartbeatHandler(Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -183,7 +188,9 @@ public class Watchdog extends Thread {
private Watchdog() {
super("watchdog");
- mHandler = new HeartbeatHandler();
+ // Explicitly bind the HeartbeatHandler to run on the ServerThread, so
+ // that it can't get accidentally bound to another thread.
+ mHandler = new HeartbeatHandler(Looper.getMainLooper());
}
public void init(Context context, BatteryService battery,
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6e81e9d..c6efe15b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2171,7 +2171,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, null, null);
+ app.info.targetSdkVersion, app.info.seinfo, null);
BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
synchronized (bs) {
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 71a6a01..6a071ef 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -188,7 +188,7 @@ public final class Installer {
}
}
- public int install(String name, int uid, int gid) {
+ public int install(String name, int uid, int gid, String seinfo) {
StringBuilder builder = new StringBuilder("install");
builder.append(' ');
builder.append(name);
@@ -196,6 +196,8 @@ public final class Installer {
builder.append(uid);
builder.append(' ');
builder.append(gid);
+ builder.append(' ');
+ builder.append(seinfo != null ? seinfo : "!");
return execute(builder.toString());
}
@@ -263,7 +265,7 @@ public final class Installer {
return execute(builder.toString());
}
- public int createUserData(String name, int uid, int userId) {
+ public int createUserData(String name, int uid, int userId, String seinfo) {
StringBuilder builder = new StringBuilder("mkuserdata");
builder.append(' ');
builder.append(name);
@@ -271,6 +273,8 @@ public final class Installer {
builder.append(uid);
builder.append(' ');
builder.append(userId);
+ builder.append(' ');
+ builder.append(seinfo != null ? seinfo : "!");
return execute(builder.toString());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 2238f17..b8324ee 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -352,6 +352,9 @@ public class PackageManagerService extends IPackageManager.Stub {
final HashMap<String, FeatureInfo> mAvailableFeatures =
new HashMap<String, FeatureInfo>();
+ // If mac_permissions.xml was found for seinfo labeling.
+ boolean mFoundPolicyFile;
+
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
@@ -1020,6 +1023,8 @@ public class PackageManagerService extends IPackageManager.Stub {
readPermissions();
+ mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
+
mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false),
mSdkVersion, mOnlyCore);
long startTime = SystemClock.uptimeMillis();
@@ -3582,16 +3587,16 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private int createDataDirsLI(String packageName, int uid) {
+ private int createDataDirsLI(String packageName, int uid, String seinfo) {
int[] users = sUserManager.getUserIds();
- int res = mInstaller.install(packageName, uid, uid);
+ int res = mInstaller.install(packageName, uid, uid, seinfo);
if (res < 0) {
return res;
}
for (int user : users) {
if (user != 0) {
res = mInstaller.createUserData(packageName,
- UserHandle.getUid(user, uid), user);
+ UserHandle.getUid(user, uid), user, seinfo);
if (res < 0) {
return res;
}
@@ -3847,6 +3852,10 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
+ if (mFoundPolicyFile) {
+ SELinuxMMAC.assignSeinfoValue(pkg);
+ }
+
pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
@@ -3985,7 +3994,8 @@ public class PackageManagerService extends IPackageManager.Stub {
recovered = true;
// And now re-install the app.
- ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
+ ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret == -1) {
// Ack should not happen!
msg = prefix + pkg.packageName
@@ -4031,7 +4041,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.v(TAG, "Want this data dir: " + dataPath);
}
//invoke installer to do the actual installation
- int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
+ int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret < 0) {
// Error from installer
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java
new file mode 100644
index 0000000..4bbdb5e
--- /dev/null
+++ b/services/java/com/android/server/pm/SELinuxMMAC.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.Signature;
+import android.os.Environment;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+import java.util.HashMap;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Centralized access to SELinux MMAC (middleware MAC) implementation.
+ * {@hide}
+ */
+public final class SELinuxMMAC {
+
+ private static final String TAG = "SELinuxMMAC";
+
+ private static final boolean DEBUG_POLICY = false;
+ private static final boolean DEBUG_POLICY_INSTALL = DEBUG_POLICY || false;
+
+ // Signature seinfo values read from policy.
+ private static final HashMap<Signature, String> sSigSeinfo =
+ new HashMap<Signature, String>();
+
+ // Package name seinfo values read from policy.
+ private static final HashMap<String, String> sPackageSeinfo =
+ new HashMap<String, String>();
+
+ // Locations of potential install policy files.
+ private static final File[] INSTALL_POLICY_FILE = {
+ new File(Environment.getDataDirectory(), "system/mac_permissions.xml"),
+ new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"),
+ null};
+
+ private static void flushInstallPolicy() {
+ sSigSeinfo.clear();
+ sPackageSeinfo.clear();
+ }
+
+ /**
+ * Parses an MMAC install policy from a predefined list of locations.
+ * @param none
+ * @return boolean indicating whether an install policy was correctly parsed.
+ */
+ public static boolean readInstallPolicy() {
+
+ return readInstallPolicy(INSTALL_POLICY_FILE);
+ }
+
+ /**
+ * Parses an MMAC install policy given as an argument.
+ * @param File object representing the path of the policy.
+ * @return boolean indicating whether the install policy was correctly parsed.
+ */
+ public static boolean readInstallPolicy(File policyFile) {
+
+ return readInstallPolicy(new File[]{policyFile,null});
+ }
+
+ private static boolean readInstallPolicy(File[] policyFiles) {
+
+ FileReader policyFile = null;
+ int i = 0;
+ while (policyFile == null && policyFiles != null && policyFiles[i] != null) {
+ try {
+ policyFile = new FileReader(policyFiles[i]);
+ break;
+ } catch (FileNotFoundException e) {
+ Slog.d(TAG,"Couldn't find install policy " + policyFiles[i].getPath());
+ }
+ i++;
+ }
+
+ if (policyFile == null) {
+ Slog.d(TAG, "No policy file found. All seinfo values will be null.");
+ return false;
+ }
+
+ Slog.d(TAG, "Using install policy file " + policyFiles[i].getPath());
+
+ flushInstallPolicy();
+
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(policyFile);
+
+ XmlUtils.beginDocument(parser, "policy");
+ while (true) {
+ XmlUtils.nextElement(parser);
+ if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
+ break;
+ }
+
+ String tagName = parser.getName();
+ if ("signer".equals(tagName)) {
+ String cert = parser.getAttributeValue(null, "signature");
+ if (cert == null) {
+ Slog.w(TAG, "<signer> without signature at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ Signature signature;
+ try {
+ signature = new Signature(cert);
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "<signer> with bad signature at "
+ + parser.getPositionDescription(), e);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String seinfo = readSeinfoTag(parser);
+ if (seinfo != null) {
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "<signer> tag: (" + cert + ") assigned seinfo="
+ + seinfo);
+
+ sSigSeinfo.put(signature, seinfo);
+ }
+ } else if ("default".equals(tagName)) {
+ String seinfo = readSeinfoTag(parser);
+ if (seinfo != null) {
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "<default> tag assigned seinfo=" + seinfo);
+
+ // The 'null' signature is the default seinfo value
+ sSigSeinfo.put(null, seinfo);
+ }
+ } else if ("package".equals(tagName)) {
+ String pkgName = parser.getAttributeValue(null, "name");
+ if (pkgName == null) {
+ Slog.w(TAG, "<package> without name at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String seinfo = readSeinfoTag(parser);
+ if (seinfo != null) {
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "<package> tag: (" + pkgName +
+ ") assigned seinfo=" + seinfo);
+
+ sPackageSeinfo.put(pkgName, seinfo);
+ }
+ } else {
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "Got execption parsing ", e);
+ } catch (IOException e) {
+ Slog.w(TAG, "Got execption parsing ", e);
+ }
+ try {
+ policyFile.close();
+ } catch (IOException e) {
+ //omit
+ }
+ return true;
+ }
+
+ private static String readSeinfoTag(XmlPullParser parser) throws
+ IOException, XmlPullParserException {
+
+ int type;
+ int outerDepth = parser.getDepth();
+ String seinfo = null;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if ("seinfo".equals(tagName)) {
+ String seinfoValue = parser.getAttributeValue(null, "value");
+ if (validateValue(seinfoValue)) {
+ seinfo = seinfoValue;
+ } else {
+ Slog.w(TAG, "<seinfo> without valid value at "
+ + parser.getPositionDescription());
+ }
+ }
+ XmlUtils.skipCurrentTag(parser);
+ }
+ return seinfo;
+ }
+
+ /**
+ * General validation routine for tag values.
+ * Returns a boolean indicating if the passed string
+ * contains only letters or underscores.
+ */
+ private static boolean validateValue(String name) {
+ if (name == null)
+ return false;
+
+ final int N = name.length();
+ if (N == 0)
+ return false;
+
+ for (int i = 0; i < N; i++) {
+ final char c = name.charAt(i);
+ if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c != '_')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Labels a package based on an seinfo tag from install policy.
+ * The label is attached to the ApplicationInfo instance of the package.
+ * @param PackageParser.Package object representing the package
+ * to labeled.
+ * @return String holding the value of the seinfo label that was assigned.
+ * Value may be null which indicates no seinfo label was assigned.
+ */
+ public static void assignSeinfoValue(PackageParser.Package pkg) {
+
+ /*
+ * Non system installed apps should be treated the same. This
+ * means that any post-loaded apk will be assigned the default
+ * tag, if one exists in the policy, else null, without respect
+ * to the signing key.
+ */
+ if (((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ||
+ ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)) {
+
+ // We just want one of the signatures to match.
+ for (Signature s : pkg.mSignatures) {
+ if (s == null)
+ continue;
+
+ if (sSigSeinfo.containsKey(s)) {
+ String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(s);
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "package (" + pkg.packageName +
+ ") labeled with seinfo=" + seinfo);
+
+ return;
+ }
+ }
+
+ // Check for seinfo labeled by package.
+ if (sPackageSeinfo.containsKey(pkg.packageName)) {
+ String seinfo = pkg.applicationInfo.seinfo = sPackageSeinfo.get(pkg.packageName);
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "package (" + pkg.packageName +
+ ") labeled with seinfo=" + seinfo);
+ return;
+ }
+ }
+
+ // If we have a default seinfo value then great, otherwise
+ // we set a null object and that is what we started with.
+ String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(null);
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "package (" + pkg.packageName +
+ ") labeled with seinfo=" + (seinfo == null ? "null" : seinfo));
+ }
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 06f11bc..a472247 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -2337,7 +2337,8 @@ final class Settings {
ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
// Need to create a data directory for all apps under this user.
installer.createUserData(ps.name,
- UserHandle.getUid(userHandle, ps.appId), userHandle);
+ UserHandle.getUid(userHandle, ps.appId), userHandle,
+ ps.pkg.applicationInfo.seinfo);
}
readDefaultPreferredAppsLPw(userHandle);
writePackageRestrictionsLPr(userHandle);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 0466c15..194c750 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -1514,7 +1514,11 @@ public class WindowManagerService extends IWindowManager.Stub
pos++;
}
if (pos >= N) {
- // All is good!
+ // Z order is good.
+ // The IM target window may be changed, so update the mTargetAppToken.
+ if (imWin != null) {
+ imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
+ }
return false;
}
}