轉自:http://blog.csdn.net/yiyaaixuexi/article/details/8495695java
在Android系統中,全部的應用程序進程,以及系統服務進程SystemServer都是由Zygote孕育fork出來的。 Zygote的native獲取主要研究dalvik/vm/native/dalvik_system_Zygote.cpp,SEAndroid管控應用程序資源存取權限,對於整個dalvik,也正是在此動的手腳。linux
首先看拋出的DalvikNativeMethod dvm_dalvik_system_Zygote,與原生Android相比,SEAndroid 在 nativeForkAndSpecialize 增長傳入了兩個String類型的參數:android
- const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
- {"nativeFork", "()I",
- Dalvik_dalvik_system_Zygote_fork },
- { "nativeForkAndSpecialize", "(II[II[[ILjava/lang/String;Ljava/lang/String;)I",
- Dalvik_dalvik_system_Zygote_forkAndSpecialize },
- { "nativeForkSystemServer", "(II[II[[IJJ)I",
- Dalvik_dalvik_system_Zygote_forkSystemServer },
- { "nativeExecShell", "(Ljava/lang/String;)V",
- Dalvik_dalvik_system_Zygote_execShell },
- { NULL, NULL, NULL },
- }
那麼這兩個參數是什麼呢?繼續追一下forkAndSpecialize。安全
-
-
-
- static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
- JValue* pResult)
- {
- pid_t pid;
-
- pid = forkAndSpecializeCommon(args, false);
-
- RETURN_INT(pid);
- }
能夠看到,增長傳入的2個參數一個是seInfo,用於定義新進程的SEAndroid信息,一個是niceName,用於定義新進程名。app
在static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)中,其中SEAndroid加入了設置SELinux安全上下文代碼段,seInfo和niceName:
socket
- #ifdef HAVE_SELINUX
- err = setSELinuxContext(uid, isSystemServer, seInfo, niceName);
- if (err < 0) {
- LOGE("cannot set SELinux context: %s\n", strerror(errno));
- dvmAbort();
- }
- free(seInfo);
- free(niceName);
- #endif
其中設置SELinux安全上下文方法實現:函數
- #ifdef HAVE_SELINUX
-
-
-
-
-
- static int setSELinuxContext(uid_t uid, bool isSystemServer,
- const char *seInfo, const char *niceName)
- {
- #ifdef HAVE_ANDROID_OS
- return selinux_android_setcontext(uid, isSystemServer, seInfo, niceName);
- #else
- return 0;
- #endif
- }
- #endif
再往上一層就到了libcore/dalvik/src/main/java/dalvik/system/Zygote.java ,Zygote類的封裝,對應forkAndSpecialize方法中添加seInfo和niceName參數傳遞。post
- public class Zygote {
- ...
- public static int forkAndSpecialize(int uid, int gid, int[] gids,
- int debugFlags, int[][] rlimits, String seInfo, String niceName) {
- preFork();
- int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits, seInfo, niceName);
- postFork();
- return pid;
- }
-
-
- native public static int nativeForkAndSpecialize(int uid, int gid,
- int[] gids, int debugFlags, int[][] rlimits, String seInfo, String niceName);
-
-
-
-
-
-
- @Deprecated
- public static int forkAndSpecialize(int uid, int gid, int[] gids,
- boolean enableDebugger, int[][] rlimits) {
- int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0;
- return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits, null, null);
- }
- ...
- }
Android應用程序啓動流程再也不贅述,當創建了ZygoteConnection對象用於socket鏈接後,接下來就是調用ZygoteConnection.runOnce函數進一步處理了。ui
源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java,其中,SEAndroid增長zygote安全策略函數,在runOnce中調用。spa
-
-
-
-
-
-
-
-
-
-
-
-
-
- private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials peer,
- String peerSecurityContext)
- throws ZygoteSecurityException {
- int peerUid = peer.getUid();
-
- if (args.invokeWith != null && peerUid != 0) {
- throw new ZygoteSecurityException("Peer is not permitted to specify "
- + "an explicit invoke-with wrapper command");
- }
-
- if (args.invokeWith != null) {
- boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
- peerSecurityContext,
- "zygote",
- "specifyinvokewith");
- if (!allowed) {
- throw new ZygoteSecurityException("Peer is not permitted to specify "
- + "an explicit invoke-with wrapper command");
- }
- }
- }
-
-
-
-
-
-
-
-
- private static void applyseInfoSecurityPolicy(
- Arguments args, Credentials peer, String peerSecurityContext)
- throws ZygoteSecurityException {
- int peerUid = peer.getUid();
-
- if (args.seInfo == null) {
-
- return;
- }
-
- if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) {
-
- throw new ZygoteSecurityException(
- "This UID may not specify SEAndroid info.");
- }
-
- boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
- peerSecurityContext,
- "zygote",
- "specifyseinfo");
- if (!allowed) {
- throw new ZygoteSecurityException(
- "Peer may not specify SEAndroid info");
- }
-
- return;
- }
理所固然的,在啓動一個新的進程時,frameworks/base/core/java/android/os/Process.java中也會加入SEAndroid信息seInfo。