diff options
-rw-r--r-- | core/java/android/os/Process.java | 10 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 115 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 2 |
3 files changed, 116 insertions, 11 deletions
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index e1bc275..50567b2 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -274,6 +274,7 @@ public class Process { * @param gids Additional group-ids associated with the process. * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. + * @param seInfo null-ok SE Android information for the new process. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. @@ -285,10 +286,11 @@ public class Process { final String niceName, int uid, int gid, int[] gids, int debugFlags, int targetSdkVersion, + String seInfo, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, - debugFlags, targetSdkVersion, zygoteArgs); + debugFlags, targetSdkVersion, seInfo, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -451,6 +453,7 @@ public class Process { * new process should setgroup() to. * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. + * @param seInfo null-ok SE Android information for the new process. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason @@ -460,6 +463,7 @@ public class Process { final int uid, final int gid, final int[] gids, int debugFlags, int targetSdkVersion, + String seInfo, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { @@ -510,6 +514,10 @@ public class Process { argsForZygote.add("--nice-name=" + niceName); } + if (seInfo != null) { + argsForZygote.add("--seinfo=" + seInfo); + } + argsForZygote.add(processClass); if (extraArgs != null) { diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 9af7e96..b016e99 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -26,6 +26,8 @@ import android.util.Log; import dalvik.system.PathClassLoader; import dalvik.system.Zygote; +import android.os.SELinux; + import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -73,6 +75,7 @@ class ZygoteConnection { private final DataOutputStream mSocketOutStream; private final BufferedReader mSocketReader; private final Credentials peer; + private final String peerSecurityContext; /** * A long-lived reference to the original command socket used to launch @@ -109,6 +112,8 @@ class ZygoteConnection { Log.e(TAG, "Cannot read peer credentials", ex); throw ex; } + + peerSecurityContext = SELinux.getPeerContext(mSocket.getFileDescriptor()); } /** @@ -207,10 +212,11 @@ class ZygoteConnection { try { parsedArgs = new Arguments(args); - applyUidSecurityPolicy(parsedArgs, peer); - applyRlimitSecurityPolicy(parsedArgs, peer); - applyCapabilitiesSecurityPolicy(parsedArgs, peer); - applyInvokeWithSecurityPolicy(parsedArgs, peer); + applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext); + applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext); + applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext); + applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext); + applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext); applyDebuggerSystemProperty(parsedArgs); applyInvokeWithSystemProperty(parsedArgs); @@ -229,7 +235,8 @@ class ZygoteConnection { } pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, - parsedArgs.gids, parsedArgs.debugFlags, rlimits); + parsedArgs.gids, parsedArgs.debugFlags, rlimits, + parsedArgs.seInfo, parsedArgs.niceName); } catch (IOException ex) { logAndPrintError(newStderr, "Exception creating pipe", ex); } catch (ErrnoException ex) { @@ -352,6 +359,10 @@ class ZygoteConnection { long permittedCapabilities; long effectiveCapabilities; + /** from --seinfo */ + boolean seInfoSpecified; + String seInfo; + /** from all --rlimit=r,c,m */ ArrayList<int[]> rlimits; @@ -429,6 +440,13 @@ class ZygoteConnection { peerWait = true; } else if (arg.equals("--runtime-init")) { runtimeInit = true; + } else if (arg.startsWith("--seinfo=")) { + if (seInfoSpecified) { + throw new IllegalArgumentException( + "Duplicate arg specified"); + } + seInfoSpecified = true; + seInfo = arg.substring(arg.indexOf('=') + 1); } else if (arg.startsWith("--capabilities=")) { if (capabilitiesSpecified) { throw new IllegalArgumentException( @@ -591,7 +609,8 @@ class ZygoteConnection { * @param peer non-null; peer credentials * @throws ZygoteSecurityException */ - private static void applyUidSecurityPolicy(Arguments args, Credentials peer) + private static void applyUidSecurityPolicy(Arguments args, Credentials peer, + String peerSecurityContext) throws ZygoteSecurityException { int peerUid = peer.getUid(); @@ -624,6 +643,17 @@ class ZygoteConnection { } } + if (args.uidSpecified || args.gidSpecified || args.gids != null) { + boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, + peerSecurityContext, + "zygote", + "specifyids"); + if (!allowed) { + throw new ZygoteSecurityException( + "Peer may not specify uid's or gid's"); + } + } + // If not otherwise specified, uid and gid are inherited from peer if (!args.uidSpecified) { args.uid = peer.getUid(); @@ -664,7 +694,7 @@ class ZygoteConnection { * @throws ZygoteSecurityException */ private static void applyRlimitSecurityPolicy( - Arguments args, Credentials peer) + Arguments args, Credentials peer, String peerSecurityContext) throws ZygoteSecurityException { int peerUid = peer.getUid(); @@ -676,6 +706,17 @@ class ZygoteConnection { "This UID may not specify rlimits."); } } + + if (args.rlimits != null) { + boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, + peerSecurityContext, + "zygote", + "specifyrlimits"); + if (!allowed) { + throw new ZygoteSecurityException( + "Peer may not specify rlimits"); + } + } } /** @@ -689,7 +730,7 @@ class ZygoteConnection { * @throws ZygoteSecurityException */ private static void applyCapabilitiesSecurityPolicy( - Arguments args, Credentials peer) + Arguments args, Credentials peer, String peerSecurityContext) throws ZygoteSecurityException { if (args.permittedCapabilities == 0 @@ -698,6 +739,15 @@ class ZygoteConnection { return; } + boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, + peerSecurityContext, + "zygote", + "specifycapabilities"); + if (!allowed) { + throw new ZygoteSecurityException( + "Peer may not specify capabilities"); + } + if (peer.getUid() == 0) { // root may specify anything return; @@ -747,7 +797,8 @@ class ZygoteConnection { * @param peer non-null; peer credentials * @throws ZygoteSecurityException */ - private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials peer) + private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials peer, + String peerSecurityContext) throws ZygoteSecurityException { int peerUid = peer.getUid(); @@ -755,6 +806,52 @@ class ZygoteConnection { throw new ZygoteSecurityException("Peer is not permitted to specify " + "an explicit invoke-with wrapper command"); } + + if (args.invokeWith != null) { + boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, + peerSecurityContext, + "zygote", + "specifyinvokewith"); + if (!allowed) { + throw new ZygoteSecurityException("Peer is not permitted to specify " + + "an explicit invoke-with wrapper command"); + } + } + } + + /** + * Applies zygote security policy for SEAndroid information. + * + * @param args non-null; zygote spawner arguments + * @param peer non-null; peer credentials + * @throws ZygoteSecurityException + */ + private static void applyseInfoSecurityPolicy( + Arguments args, Credentials peer, String peerSecurityContext) + throws ZygoteSecurityException { + int peerUid = peer.getUid(); + + if (args.seInfo == null) { + // nothing to check + return; + } + + if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) { + // All peers with UID other than root or SYSTEM_UID + throw new ZygoteSecurityException( + "This UID may not specify SEAndroid info."); + } + + boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, + peerSecurityContext, + "zygote", + "specifyseinfo"); + if (!allowed) { + throw new ZygoteSecurityException( + "Peer may not specify SEAndroid info"); + } + + return; } /** diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 6190a63..0a4d19f 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1967,7 +1967,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, - app.info.targetSdkVersion, null); + app.info.targetSdkVersion, null, null); BatteryStatsImpl bs = app.batteryStats.getBatteryStats(); synchronized (bs) { |