Merge "Pass additional inputs when spawning apps via the Zygote and add SELinux permission checks."

This commit is contained in:
Kenny Root
2012-06-21 11:05:54 -07:00
committed by android code review
3 changed files with 116 additions and 11 deletions

View File

@ -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) {

View File

@ -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;
}
/**

View File

@ -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) {