19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.os; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Credentials; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.LocalSocket; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 225b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkeyimport android.os.SELinux; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport dalvik.system.PathClassLoader; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport dalvik.system.Zygote; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedReader; 30ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport java.io.DataInputStream; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.DataOutputStream; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 33ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport java.io.FileInputStream; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStreamReader; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintStream; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 40ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport libcore.io.ErrnoException; 41ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport libcore.io.IoUtils; 42ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport libcore.io.Libcore; 43ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A connection that can make spawn requests. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass ZygoteConnection { 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "Zygote"; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** a prototype instance for a future List.toArray() */ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[][] intArray2d = new int[0][0]; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.net.LocalSocket#setSoTimeout} value for connections. 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Effectively, the amount of time a requestor has between the start of 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the request and the completed request. The select-loop mode Zygote 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * doesn't have the logic to return to the select loop in the middle of 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a request, so we need to time out here to avoid being denial-of-serviced. 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int CONNECTION_TIMEOUT_MILLIS = 1000; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** max number of arguments that a connection can specify */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_ZYGOTE_ARGC=1024; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The command socket. 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * mSocket is retained in the child process in "peer wait" mode, so 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that it closes when the child process terminates. In other cases, 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it is closed in the peer. 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final LocalSocket mSocket; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final DataOutputStream mSocketOutStream; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BufferedReader mSocketReader; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Credentials peer; 7683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley private final String peerSecurityContext; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A long-lived reference to the original command socket used to launch 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this peer. If "peer wait" mode is specified, the process that requested 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the new VM instance intends to track the lifetime of the spawned instance 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * via the command socket. In this case, the command socket is closed 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the Zygote and placed here in the spawned instance so that it will 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not be collected and finalized. This field remains null at all times 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the original Zygote process, and in all spawned processes where 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "peer-wait" mode was not requested. 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static LocalSocket sPeerWaitSocket = null; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs instance from connected socket. 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param socket non-null; connected socket 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZygoteConnection(LocalSocket socket) throws IOException { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSocket = socket; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSocketOutStream 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new DataOutputStream(socket.getOutputStream()); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSocketReader = new BufferedReader( 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new InputStreamReader(socket.getInputStream()), 256); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project peer = mSocket.getPeerCredentials(); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Cannot read peer credentials", ex); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw ex; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 11483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley peerSecurityContext = SELinux.getPeerContext(mSocket.getFileDescriptor()); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the file descriptor of the associated socket. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return null-ok; file descriptor 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor getFileDesciptor() { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSocket.getFileDescriptor(); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Reads start commands from an open command socket. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start commands are presently a pair of newline-delimited lines 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indicating a) class to invoke main() on b) nice name to set argv[0] to. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Continues to read commands and forkAndSpecialize children until 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the socket is closed. This method is used in ZYGOTE_FORK_MODE 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main() 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * method in child process 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void run() throws ZygoteInit.MethodAndArgsCaller { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int loopCount = ZygoteInit.GC_LOOP_COUNT; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call gc() before we block in readArgumentList(). 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It's work that has to be done anyway, and it's better 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to avoid making every child do it. It will also 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * madvise() any free memory as a side-effect. 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call it every time, because walking the entire 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * heap is a lot of overhead to free a few hundred bytes. 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (loopCount <= 0) { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZygoteInit.gc(); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loopCount = ZygoteInit.GC_LOOP_COUNT; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loopCount--; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (runOnce()) { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Reads one start command from the command socket. If successful, 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller} 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * exception is thrown in that child while in the parent process, 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the method returns normally. On failure, the child is not 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * spawned and messages are printed to the log and stderr. Returns 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a boolean status value indicating whether an end-of-file on the command 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * socket has been encountered. 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return false if command socket should continue to be read from, or 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * true if an end-of-file has been encountered. 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main() 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * method in child process 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String args[]; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Arguments parsedArgs = null; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor[] descriptors; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args = readArgumentList(); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project descriptors = mSocket.getAncillaryFileDescriptors(); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "IOException on command socket " + ex.getMessage()); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closeSocket(); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args == null) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // EOF reached. 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closeSocket(); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** the stderr of the most recent request, if avail */ 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PrintStream newStderr = null; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (descriptors != null && descriptors.length >= 3) { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newStderr = new PrintStream( 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new FileOutputStream(descriptors[2])); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 206ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown int pid = -1; 207ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown FileDescriptor childPipeFd = null; 208ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown FileDescriptor serverPipeFd = null; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parsedArgs = new Arguments(args); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext); 21483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext); 21583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext); 21683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext); 21783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext); 218ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 219ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown applyDebuggerSystemProperty(parsedArgs); 220ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown applyInvokeWithSystemProperty(parsedArgs); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[][] rlimits = null; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (parsedArgs.rlimits != null) { 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rlimits = parsedArgs.rlimits.toArray(intArray2d); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 228ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) { 229ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown FileDescriptor[] pipeFds = Libcore.os.pipe(); 230ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown childPipeFd = pipeFds[1]; 231ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown serverPipeFd = pipeFds[0]; 232ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown ZygoteInit.setCloseOnExec(serverPipeFd, true); 233ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 234ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 2355b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, 2365b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, 2375b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey parsedArgs.niceName); 238ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } catch (IOException ex) { 239ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown logAndPrintError(newStderr, "Exception creating pipe", ex); 240ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } catch (ErrnoException ex) { 241ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown logAndPrintError(newStderr, "Exception creating pipe", ex); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalArgumentException ex) { 243ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown logAndPrintError(newStderr, "Invalid zygote arguments", ex); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ZygoteSecurityException ex) { 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project logAndPrintError(newStderr, 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Zygote security policy prevents request: ", ex); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown try { 250ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (pid == 0) { 251ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // in child 252ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown IoUtils.closeQuietly(serverPipeFd); 253ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown serverPipeFd = null; 254ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); 255ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 256ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // should never get here, the child is expected to either 257ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // throw ZygoteInit.MethodAndArgsCaller or exec(). 258ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown return true; 259ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else { 260ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // in parent...pid of < 0 means failure 261ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown IoUtils.closeQuietly(childPipeFd); 262ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown childPipeFd = null; 263ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); 264ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 265ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } finally { 266ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown IoUtils.closeQuietly(childPipeFd); 267ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown IoUtils.closeQuietly(serverPipeFd); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Closes socket associated with this connection. 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void closeSocket() { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSocket.close(); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Exception while closing command " 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "socket in parent", ex); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 284ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Handles argument parsing for args related to the zygote spawner. 285ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Current recognized args: 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul> 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --setuid=<i>uid of child process, defaults to 0</i> 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --setgid=<i>gid of child process, defaults to 0</i> 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --setgroups=<i>comma-separated list of supplimentary gid's</i> 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --capabilities=<i>a pair of comma-separated integer strings 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indicating Linux capabilities(2) set for child. The first string 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * represents the <code>permitted</code> set, and the second the 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>effective</code> set. Precede each with 0 or 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 0x for octal or hexidecimal value. If unspecified, both default to 0. 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This parameter is only applied if the uid of the new process will 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be non-0. </i> 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --rlimit=r,c,m<i>tuple of values for setrlimit() call. 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>r</code> is the resource, <code>c</code> and <code>m</code> 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are the settings for current and max value.</i> 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --peer-wait indicates that the command socket should 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be inherited by (and set to close-on-exec in) the spawned process 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and used to track the lifetime of that process. The spawning process 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * then exits. Without this flag, it is retained by the spawning process 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (and closed in the child) in expectation of a new spawn request. 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --classpath=<i>colon-separated classpath</i> indicates 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that the specified class (which must b first non-flag argument) should 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be loaded from jar files in the specified classpath. Incompatible with 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * --runtime-init 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> --runtime-init indicates that the remaining arg list should 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be handed off to com.android.internal.os.RuntimeInit, rather than 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * processed directly 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Android runtime startup (eg, Binder initialization) is also eschewed. 314ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * <li> --nice-name=<i>nice name to appear in ps</i> 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> If <code>--runtime-init</code> is present: 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * [--] <args for RuntimeInit > 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> If <code>--runtime-init</code> is absent: 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * [--] <classname> [args...] 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul> 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class Arguments { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from --setuid */ 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int uid = 0; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean uidSpecified; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from --setgid */ 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gid = 0; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean gidSpecified; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from --setgroups */ 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] gids; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from --peer-wait */ 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean peerWait; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33623085b781e145ed684e7270af1d5ced6800b8effBen Cheng /** 337ae07ecf3766c38af1c12822458b98036b28bd4c0Elliott Hughes * From --enable-debugger, --enable-checkjni, --enable-assert, 338ae07ecf3766c38af1c12822458b98036b28bd4c0Elliott Hughes * --enable-safemode, and --enable-jni-logging. 33923085b781e145ed684e7270af1d5ced6800b8effBen Cheng */ 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int debugFlags; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3425b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey /** From --mount-external */ 3435b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; 3445b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey 345e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes /** from --target-sdk-version. */ 346e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes int targetSdkVersion; 347e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes boolean targetSdkVersionSpecified; 348e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from --classpath */ 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String classpath; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from --runtime-init */ 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean runtimeInit; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 355ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown /** from --nice-name */ 356ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown String niceName; 357ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from --capabilities */ 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean capabilitiesSpecified; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long permittedCapabilities; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long effectiveCapabilities; 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley /** from --seinfo */ 36483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley boolean seInfoSpecified; 36583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley String seInfo; 36683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** from all --rlimit=r,c,m */ 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<int[]> rlimits; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 370ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown /** from --invoke-with */ 371ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown String invokeWith; 372ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Any args after and including the first non-option arg 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (or after a '--') 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String remainingArgs[]; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs instance and parses args 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args zygote command-line args 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IllegalArgumentException 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Arguments(String args[]) throws IllegalArgumentException { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parseArgs(args); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parses the commandline arguments intended for the Zygote spawner 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (such as "--setuid=" and "--setgid=") and creates an array 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * containing the remaining args. 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Per security review bug #1112214, duplicate args are disallowed in 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * critical cases to make injection harder. 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void parseArgs(String args[]) 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IllegalArgumentException { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int curArg = 0; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for ( /* curArg */ ; curArg < args.length; curArg++) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String arg = args[curArg]; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (arg.equals("--")) { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project curArg++; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.startsWith("--setuid=")) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uidSpecified) { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Duplicate arg specified"); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uidSpecified = true; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uid = Integer.parseInt( 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project arg.substring(arg.indexOf('=') + 1)); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.startsWith("--setgid=")) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (gidSpecified) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Duplicate arg specified"); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gidSpecified = true; 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gid = Integer.parseInt( 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project arg.substring(arg.indexOf('=') + 1)); 422e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes } else if (arg.startsWith("--target-sdk-version=")) { 423e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes if (targetSdkVersionSpecified) { 424e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes throw new IllegalArgumentException( 425e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes "Duplicate target-sdk-version specified"); 426e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes } 427e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes targetSdkVersionSpecified = true; 428e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes targetSdkVersion = Integer.parseInt( 429e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes arg.substring(arg.indexOf('=') + 1)); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.equals("--enable-debugger")) { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; 43223085b781e145ed684e7270af1d5ced6800b8effBen Cheng } else if (arg.equals("--enable-safemode")) { 43323085b781e145ed684e7270af1d5ced6800b8effBen Cheng debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.equals("--enable-checkjni")) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; 436ae07ecf3766c38af1c12822458b98036b28bd4c0Elliott Hughes } else if (arg.equals("--enable-jni-logging")) { 437ae07ecf3766c38af1c12822458b98036b28bd4c0Elliott Hughes debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.equals("--enable-assert")) { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.equals("--peer-wait")) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project peerWait = true; 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.equals("--runtime-init")) { 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project runtimeInit = true; 44483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } else if (arg.startsWith("--seinfo=")) { 44583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (seInfoSpecified) { 44683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throw new IllegalArgumentException( 44783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "Duplicate arg specified"); 44883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 44983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley seInfoSpecified = true; 45083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley seInfo = arg.substring(arg.indexOf('=') + 1); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.startsWith("--capabilities=")) { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (capabilitiesSpecified) { 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Duplicate arg specified"); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project capabilitiesSpecified = true; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String capString = arg.substring(arg.indexOf('=')+1); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] capStrings = capString.split(",", 2); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (capStrings.length == 1) { 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effectiveCapabilities = Long.decode(capStrings[0]); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permittedCapabilities = effectiveCapabilities; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permittedCapabilities = Long.decode(capStrings[0]); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effectiveCapabilities = Long.decode(capStrings[1]); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.startsWith("--rlimit=")) { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Duplicate --rlimit arguments are specifically allowed. 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] limitStrings 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = arg.substring(arg.indexOf('=')+1).split(","); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (limitStrings.length != 3) { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "--rlimit= should have 3 comma-delimited ints"); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] rlimitTuple = new int[limitStrings.length]; 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i=0; i < limitStrings.length; i++) { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rlimitTuple[i] = Integer.parseInt(limitStrings[i]); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rlimits == null) { 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rlimits = new ArrayList(); 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rlimits.add(rlimitTuple); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.equals("-classpath")) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (classpath != null) { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Duplicate arg specified"); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classpath = args[++curArg]; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IndexOutOfBoundsException ex) { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "-classpath requires argument"); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (arg.startsWith("--setgroups=")) { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (gids != null) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Duplicate arg specified"); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] params 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = arg.substring(arg.indexOf('=') + 1).split(","); 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gids = new int[params.length]; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = params.length - 1; i >= 0 ; i--) { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gids[i] = Integer.parseInt(params[i]); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 513ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (arg.equals("--invoke-with")) { 514ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (invokeWith != null) { 515ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown throw new IllegalArgumentException( 516ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown "Duplicate arg specified"); 517ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 518ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown try { 519ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown invokeWith = args[++curArg]; 520ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } catch (IndexOutOfBoundsException ex) { 521ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown throw new IllegalArgumentException( 522ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown "--invoke-with requires argument"); 523ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 524ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (arg.startsWith("--nice-name=")) { 525ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (niceName != null) { 526ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown throw new IllegalArgumentException( 527ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown "Duplicate arg specified"); 528ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 529ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown niceName = arg.substring(arg.indexOf('=') + 1); 5305b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey } else if (arg.equals("--mount-external-multiuser")) { 5315b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER; 532e217ee4d7a8223289a1af7363627c69956c46d41Jeff Sharkey } else if (arg.equals("--mount-external-multiuser-all")) { 533e217ee4d7a8223289a1af7363627c69956c46d41Jeff Sharkey mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (runtimeInit && classpath != null) { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "--runtime-init and -classpath are incompatible"); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remainingArgs = new String[args.length - curArg]; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(args, curArg, remainingArgs, 0, 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remainingArgs.length); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Reads an argument list from the command socket/ 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Argument list or null if EOF is reached 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException passed straight through 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] readArgumentList() 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See android.os.Process.zygoteSendArgsAndGetPid() 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Presently the wire format to the zygote process is: 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a) a count of arguments (argc, in essence) 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * b) a number of newline-separated argument strings equal to count 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * After the zygote process reads these it will write the pid of 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the child or -1 on failure. 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int argc; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = mSocketReader.readLine(); 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s == null) { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // EOF reached. 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project argc = Integer.parseInt(s); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "invalid Zygote wire format: non-int at argc"); 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("invalid wire format"); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // See bug 1092107: large argc can be used for a DOS attack 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (argc > MAX_ZYGOTE_ARGC) { 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("max arg count exceeded"); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] result = new String[argc]; 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < argc; i++) { 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result[i] = mSocketReader.readLine(); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result[i] == null) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We got an unexpected EOF. 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("truncated request"); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Applies zygote security policy per bugs #875058 and #1082165. 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Based on the credentials of the process issuing a zygote command: 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ol> 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> uid 0 (root) may specify any uid, gid, and setgroups() list 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> uid 1000 (Process.SYSTEM_UID) may specify any uid > 1000 in normal 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * operation. It may also specify any gid and setgroups() list it chooses. 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In factory test mode, it may specify any UID. 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Any other uid may not specify any uid, gid, or setgroups list. The 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * uid and gid will be inherited from the requesting process. 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul> 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args non-null; zygote spawner arguments 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param peer non-null; peer credentials 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws ZygoteSecurityException 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 61783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley private static void applyUidSecurityPolicy(Arguments args, Credentials peer, 61883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley String peerSecurityContext) 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws ZygoteSecurityException { 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int peerUid = peer.getUid(); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (peerUid == 0) { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Root can do what it wants 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (peerUid == Process.SYSTEM_UID ) { 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // System UID is restricted, except in factory test mode 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String factoryTest = SystemProperties.get("ro.factorytest"); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean uidRestricted; 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* In normal operation, SYSTEM_UID can only specify a restricted 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid. 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uidRestricted 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = !(factoryTest.equals("1") || factoryTest.equals("2")); 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uidRestricted 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && args.uidSpecified && (args.uid < Process.SYSTEM_UID)) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ZygoteSecurityException( 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "System UID may not launch process with UID < " 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Process.SYSTEM_UID); 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Everything else 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args.uidSpecified || args.gidSpecified 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || args.gids != null) { 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ZygoteSecurityException( 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "App UIDs may not specify uid's or gid's"); 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 65183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (args.uidSpecified || args.gidSpecified || args.gids != null) { 65283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, 65383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley peerSecurityContext, 65483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "zygote", 65583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "specifyids"); 65683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (!allowed) { 65783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throw new ZygoteSecurityException( 65883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "Peer may not specify uid's or gid's"); 65983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 66083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 66183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If not otherwise specified, uid and gid are inherited from peer 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!args.uidSpecified) { 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args.uid = peer.getUid(); 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args.uidSpecified = true; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!args.gidSpecified) { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args.gid = peer.getGid(); 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args.gidSpecified = true; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 675ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Applies debugger system properties to the zygote arguments. 676ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If "ro.debuggable" is "1", all apps are debuggable. Otherwise, 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the debugger state is specified via the "--enable-debugger" flag 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the spawn request. 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args non-null; zygote spawner args 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 683ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown public static void applyDebuggerSystemProperty(Arguments args) { 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ("1".equals(SystemProperties.get("ro.debuggable"))) { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args.debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Applies zygote security policy per bug #1042973. Based on the credentials 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the process issuing a zygote command: 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ol> 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> peers of uid 0 (root) and uid 1000 (Process.SYSTEM_UID) 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * may specify any rlimits. 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> All other uids may not specify rlimits. 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul> 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args non-null; zygote spawner arguments 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param peer non-null; peer credentials 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws ZygoteSecurityException 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void applyRlimitSecurityPolicy( 70283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley Arguments args, Credentials peer, String peerSecurityContext) 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws ZygoteSecurityException { 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int peerUid = peer.getUid(); 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) { 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // All peers with UID other than root or SYSTEM_UID 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args.rlimits != null) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ZygoteSecurityException( 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "This UID may not specify rlimits."); 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 71483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 71583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (args.rlimits != null) { 71683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, 71783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley peerSecurityContext, 71883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "zygote", 71983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "specifyrlimits"); 72083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (!allowed) { 72183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throw new ZygoteSecurityException( 72283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "Peer may not specify rlimits"); 72383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 72483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Applies zygote security policy per bug #1042973. A root peer may 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * spawn an instance with any capabilities. All other uids may spawn 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instances with any of the capabilities in the peer's permitted set 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but no more. 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args non-null; zygote spawner arguments 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param peer non-null; peer credentials 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws ZygoteSecurityException 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void applyCapabilitiesSecurityPolicy( 73883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley Arguments args, Credentials peer, String peerSecurityContext) 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws ZygoteSecurityException { 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (args.permittedCapabilities == 0 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && args.effectiveCapabilities == 0) { 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // nothing to check 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 74783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, 74883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley peerSecurityContext, 74983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "zygote", 75083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "specifycapabilities"); 75183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (!allowed) { 75283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throw new ZygoteSecurityException( 75383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "Peer may not specify capabilities"); 75483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 75583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (peer.getUid() == 0) { 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // root may specify anything 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long permittedCaps; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project permittedCaps = ZygoteInit.capgetPermitted(peer.getPid()); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ZygoteSecurityException( 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Error retrieving peer's capabilities."); 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Ensure that the client did not specify an effective set larger 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * than the permitted set. The kernel will enforce this too, but we 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * do it here to make the following check easier. 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (((~args.permittedCapabilities) & args.effectiveCapabilities) != 0) { 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ZygoteSecurityException( 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Effective capabilities cannot be superset of " 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " permitted capabilities" ); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Ensure that the new permitted (and thus the new effective) set is 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a subset of the peer process's permitted set 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (((~permittedCaps) & args.permittedCapabilities) != 0) { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ZygoteSecurityException( 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Peer specified unpermitted capabilities" ); 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 793ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Applies zygote security policy. 794ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Based on the credentials of the process issuing a zygote command: 795ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * <ol> 796ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * <li> uid 0 (root) may specify --invoke-with to launch Zygote with a 797ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * wrapper command. 798ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * <li> Any other uid may not specify any invoke-with argument. 799ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * </ul> 800ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * 801ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * @param args non-null; zygote spawner arguments 802ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * @param peer non-null; peer credentials 803ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * @throws ZygoteSecurityException 804ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown */ 80583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials peer, 80683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley String peerSecurityContext) 807ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown throws ZygoteSecurityException { 808ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown int peerUid = peer.getUid(); 809ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 810ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (args.invokeWith != null && peerUid != 0) { 811ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown throw new ZygoteSecurityException("Peer is not permitted to specify " 812ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown + "an explicit invoke-with wrapper command"); 813ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 81483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 81583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (args.invokeWith != null) { 81683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, 81783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley peerSecurityContext, 81883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "zygote", 81983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "specifyinvokewith"); 82083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (!allowed) { 82183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throw new ZygoteSecurityException("Peer is not permitted to specify " 82283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley + "an explicit invoke-with wrapper command"); 82383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 82483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 82583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 82683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 82783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley /** 82883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley * Applies zygote security policy for SEAndroid information. 82983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley * 83083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley * @param args non-null; zygote spawner arguments 83183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley * @param peer non-null; peer credentials 83283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley * @throws ZygoteSecurityException 83383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley */ 83483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley private static void applyseInfoSecurityPolicy( 83583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley Arguments args, Credentials peer, String peerSecurityContext) 83683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throws ZygoteSecurityException { 83783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley int peerUid = peer.getUid(); 83883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 83983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (args.seInfo == null) { 84083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley // nothing to check 84183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley return; 84283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 84383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 84483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) { 84583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley // All peers with UID other than root or SYSTEM_UID 84683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throw new ZygoteSecurityException( 84783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "This UID may not specify SEAndroid info."); 84883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 84983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 85083d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext, 85183d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley peerSecurityContext, 85283d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "zygote", 85383d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "specifyseinfo"); 85483d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley if (!allowed) { 85583d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley throw new ZygoteSecurityException( 85683d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley "Peer may not specify SEAndroid info"); 85783d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley } 85883d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley 85983d9eda9c2c411e3480c52f01e192bf3c86be8e9Stephen Smalley return; 860ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 861ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 862ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown /** 863ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Applies invoke-with system properties to the zygote arguments. 864ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * 865ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * @param parsedArgs non-null; zygote args 866ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown */ 867ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown public static void applyInvokeWithSystemProperty(Arguments args) { 868ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (args.invokeWith == null && args.niceName != null) { 869ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (args.niceName != null) { 870ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown String property = "wrap." + args.niceName; 871ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (property.length() > 31) { 872ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown property = property.substring(0, 31); 873ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 874ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown args.invokeWith = SystemProperties.get(property); 875ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (args.invokeWith != null && args.invokeWith.length() == 0) { 876ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown args.invokeWith = null; 877ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 878ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 879ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 880ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 881ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 882ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown /** 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handles post-fork setup of child proc, closing sockets as appropriate, 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if successful or returning if failed. 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parsedArgs non-null; zygote args 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param descriptors null-ok; new file descriptors for stdio if available. 889ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * @param pipeFd null-ok; pipe for communication back to Zygote. 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newStderr null-ok; stream to use for stderr until stdio 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is reopened. 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws ZygoteInit.MethodAndArgsCaller on success to 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * trampoline to code that invokes static main. 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleChildProc(Arguments parsedArgs, 897ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws ZygoteInit.MethodAndArgsCaller { 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the socket, unless we're in "peer wait" mode, in which 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * case it's used to track the liveness of this process. 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (parsedArgs.peerWait) { 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(), true); 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sPeerWaitSocket = mSocket; 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Zygote Child: error setting peer wait " 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + "socket to be close-on-exec", ex); 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closeSocket(); 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZygoteInit.closeServerSocket(); 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (descriptors != null) { 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZygoteInit.reopenStdio(descriptors[0], 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project descriptors[1], descriptors[2]); 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (FileDescriptor fd: descriptors) { 924ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown IoUtils.closeQuietly(fd); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newStderr = System.err; 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error reopening stdio", ex); 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 932ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (parsedArgs.niceName != null) { 933ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown Process.setArgV0(parsedArgs.niceName); 934ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 936ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (parsedArgs.runtimeInit) { 937ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (parsedArgs.invokeWith != null) { 938ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown WrapperInit.execApplication(parsedArgs.invokeWith, 939e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes parsedArgs.niceName, parsedArgs.targetSdkVersion, 940e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes pipeFd, parsedArgs.remainingArgs); 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 942e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, 943e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes parsedArgs.remainingArgs); 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 945ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else { 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String className; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project className = parsedArgs.remainingArgs[0]; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (ArrayIndexOutOfBoundsException ex) { 950ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown logAndPrintError(newStderr, 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Missing required class name argument", null); 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 955ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1]; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(parsedArgs.remainingArgs, 1, 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mainArgs, 0, mainArgs.length); 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (parsedArgs.invokeWith != null) { 960ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown WrapperInit.execStandalone(parsedArgs.invokeWith, 961ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown parsedArgs.classpath, className, mainArgs); 962ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else { 963ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown ClassLoader cloader; 964ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (parsedArgs.classpath != null) { 965ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown cloader = new PathClassLoader(parsedArgs.classpath, 966ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown ClassLoader.getSystemClassLoader()); 967ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else { 968ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown cloader = ClassLoader.getSystemClassLoader(); 969ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 970ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 971ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown try { 972ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown ZygoteInit.invokeStaticMain(cloader, className, mainArgs); 973ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } catch (RuntimeException ex) { 974ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown logAndPrintError(newStderr, "Error starting.", ex); 975ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handles post-fork cleanup of parent proc 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param pid != 0; pid of child if > 0 or indication of failed fork 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if < 0; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param descriptors null-ok; file descriptors for child's new stdio if 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified. 987ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * @param pipeFd null-ok; pipe for communication with child. 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parsedArgs non-null; zygote args 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true for "exit command loop" and false for "continue command 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * loop" 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean handleParentProc(int pid, 993ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) { 994ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 995ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (pid > 0) { 996ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown setChildPgid(pid); 997ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 998ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 999ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (descriptors != null) { 1000ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown for (FileDescriptor fd: descriptors) { 1001ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown IoUtils.closeQuietly(fd); 1002ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 1003ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10053f9dd287b99340efaaa257759e71a8f81b2ed113Jeff Brown boolean usingWrapper = false; 1006ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (pipeFd != null && pid > 0) { 1007ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown DataInputStream is = new DataInputStream(new FileInputStream(pipeFd)); 1008ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown int innerPid = -1; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1010ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown innerPid = is.readInt(); 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 1012ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown Log.w(TAG, "Error reading pid from wrapped process, child may have died", ex); 1013ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } finally { 1014ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown try { 1015ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown is.close(); 1016ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } catch (IOException ex) { 1017ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1020ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // Ensure that the pid reported by the wrapped process is either the 1021ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // child process that we forked, or a descendant of it. 1022ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (innerPid > 0) { 1023ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown int parentPid = innerPid; 1024ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown while (parentPid > 0 && parentPid != pid) { 1025ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown parentPid = Process.getParentPid(parentPid); 1026ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 1027ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (parentPid > 0) { 1028ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown Log.i(TAG, "Wrapped process has pid " + innerPid); 1029ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown pid = innerPid; 10303f9dd287b99340efaaa257759e71a8f81b2ed113Jeff Brown usingWrapper = true; 1031ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else { 1032ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown Log.w(TAG, "Wrapped process reported a pid that is not a child of " 1033ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown + "the process that we forked: childPid=" + pid 1034ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown + " innerPid=" + innerPid); 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSocketOutStream.writeInt(pid); 10413f9dd287b99340efaaa257759e71a8f81b2ed113Jeff Brown mSocketOutStream.writeBoolean(usingWrapper); 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error reading from command socket", ex); 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the peer wants to use the socket to wait on the 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * newly spawned process, then we're all done. 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (parsedArgs.peerWait) { 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSocket.close(); 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Zygote: error closing sockets", ex); 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1062ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown private void setChildPgid(int pid) { 1063ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // Try to move the new child into the peer's process group. 1064ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown try { 1065ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown ZygoteInit.setpgid(pid, ZygoteInit.getpgid(peer.getPid())); 1066ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } catch (IOException ex) { 1067ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // This exception is expected in the case where 1068ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // the peer is not in our session 1069ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // TODO get rid of this log message in the case where 1070ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // getsid(0) != getsid(peer.getPid()) 1071ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown Log.i(TAG, "Zygote: setpgid failed. This is " 1072ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown + "normal if peer is not in our session"); 1073ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 1074ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 1075ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Logs an error message and prints it to the specified stream, if 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provided 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newStderr null-ok; a standard error stream 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param message non-null; error message 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param ex null-ok an exception 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void logAndPrintError (PrintStream newStderr, 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String message, Throwable ex) { 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, message, ex); 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newStderr != null) { 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newStderr.println(message + (ex == null ? "" : ex)); 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1092