Merge "Pass additional inputs when spawning apps via the Zygote and add SELinux permission checks."
This commit is contained in:
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user