zoukankan      html  css  js  c++  java
  • Android 安全攻防(三): SEAndroid Zygote

    转自:http://blog.csdn.net/yiyaaixuexi/article/details/8495695

    在Android系统中,所有的应用程序进程,以及系统服务进程SystemServer都是由Zygote孕育fork出来的。 Zygote的native获取主要研究dalvik/vm/native/dalvik_system_Zygote.cpp,SEAndroid管控应用程序资源存取权限,对于整个dalvik,也正是在此动的手脚。

     

    首先看抛出的DalvikNativeMethod dvm_dalvik_system_Zygote,与原生Android相比,SEAndroid 在 nativeForkAndSpecialize 增加传入了两个String类型的参数:

    1. const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {  
    2.     {"nativeFork""()I",  
    3.         Dalvik_dalvik_system_Zygote_fork },  
    4.     { "nativeForkAndSpecialize""(II[II[[ILjava/lang/String;Ljava/lang/String;)I",  
    5.         Dalvik_dalvik_system_Zygote_forkAndSpecialize },  
    6.     { "nativeForkSystemServer""(II[II[[IJJ)I",  
    7.         Dalvik_dalvik_system_Zygote_forkSystemServer },  
    8.     { "nativeExecShell""(Ljava/lang/String;)V",  
    9.         Dalvik_dalvik_system_Zygote_execShell },  
    10.     { NULL, NULL, NULL },  
    11. }  


    那么这两个参数是什么呢?继续追一下forkAndSpecialize。

    1. /* native public static int forkAndSpecialize(int uid, int gid, 
    2. * int[] gids, int debugFlags, String seInfo, String niceName); 
    3. */  
    4. static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,  
    5. JValue* pResult)  
    6. {  
    7.     pid_t pid;  
    8.   
    9.     pid = forkAndSpecializeCommon(args, false);  
    10.   
    11.     RETURN_INT(pid);  
    12. }  


    可以看到,增加传入的2个参数一个是seInfo,用于定义新进程的SEAndroid信息,一个是niceName,用于定义新进程名。

    在static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)中,其中SEAndroid加入了设置SELinux安全上下文代码段,seInfo和niceName:

    1. #ifdef HAVE_SELINUX  
    2.     err = setSELinuxContext(uid, isSystemServer, seInfo, niceName);  
    3.     if (err < 0) {  
    4.         LOGE("cannot set SELinux context: %s ", strerror(errno));  
    5.         dvmAbort();  
    6.     }  
    7.     free(seInfo);  
    8.     free(niceName);  
    9. #endif  


    其中设置SELinux安全上下文方法实现:

    1. #ifdef HAVE_SELINUX  
    2. /* 
    3. * Set SELinux security context. 
    4. * 
    5. * Returns 0 on success, -1 on failure. 
    6. */  
    7. static int setSELinuxContext(uid_t uid, bool isSystemServer,  
    8. const char *seInfo, const char *niceName)  
    9. {  
    10. #ifdef HAVE_ANDROID_OS  
    11.     return selinux_android_setcontext(uid, isSystemServer, seInfo, niceName);  
    12. #else  
    13.     return 0;  
    14. #endif  
    15. }  
    16. #endif  



    再往上一层就到了libcore/dalvik/src/main/java/dalvik/system/Zygote.java ,Zygote类的封装,对应forkAndSpecialize方法中添加seInfo和niceName参数传递。

    1. public class Zygote {  
    2. ...  
    3.     public static int forkAndSpecialize(int uid, int gid, int[] gids,  
    4.             int debugFlags, int[][] rlimits, String seInfo, String niceName) {  
    5.         preFork();  
    6.         int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits, seInfo, niceName);  
    7.         postFork();  
    8.         return pid;  
    9.     }  
    10.   
    11.   
    12.     native public static int nativeForkAndSpecialize(int uid, int gid,  
    13.             int[] gids, int debugFlags, int[][] rlimits, String seInfo, String niceName);  
    14.   
    15.   
    16.     /** 
    17.      * Forks a new VM instance. 
    18.      * @deprecated use {@link Zygote#forkAndSpecialize(int, int, int[], int, int[][])} 
    19.      */  
    20.     @Deprecated  
    21.     public static int forkAndSpecialize(int uid, int gid, int[] gids,  
    22.             boolean enableDebugger, int[][] rlimits) {  
    23.         int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0;  
    24.         return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits, nullnull);  
    25.     }  
    26. ...  
    27. }  

    Android应用程序启动流程不再赘述,当建立了ZygoteConnection对象用于socket连接后,接下来就是调用ZygoteConnection.runOnce函数进一步处理了。

    源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java,其中,SEAndroid增加zygote安全策略函数,在runOnce中调用。

    1. /** 
    2.     * Applies zygote security policy. 
    3.     * Based on the credentials of the process issuing a zygote command: 
    4.     * <ol> 
    5.     * <li> uid 0 (root) may specify --invoke-with to launch Zygote with a 
    6.     * wrapper command. 
    7.     * <li> Any other uid may not specify any invoke-with argument. 
    8.     * </ul> 
    9.     * 
    10.     * @param args non-null; zygote spawner arguments 
    11.     * @param peer non-null; peer credentials 
    12.     * @throws ZygoteSecurityException 
    13.     */  
    14.    private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials peer,  
    15.            String peerSecurityContext)  
    16.            throws ZygoteSecurityException {  
    17.        int peerUid = peer.getUid();  
    18.   
    19.        if (args.invokeWith != null && peerUid != 0) {  
    20.            throw new ZygoteSecurityException("Peer is not permitted to specify "  
    21.                    + "an explicit invoke-with wrapper command");  
    22.        }  
    23.   
    24.        if (args.invokeWith != null) {  
    25.            boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,  
    26.                                                         peerSecurityContext,  
    27.                                                         "zygote",  
    28.                                                         "specifyinvokewith");  
    29.            if (!allowed) {  
    30.                throw new ZygoteSecurityException("Peer is not permitted to specify "  
    31.                    + "an explicit invoke-with wrapper command");  
    32.            }  
    33.        }  
    34.    }  
    35.   
    36.    /** 
    37.     * Applies zygote security policy for SEAndroid information. 
    38.     * 
    39.     * @param args non-null; zygote spawner arguments 
    40.     * @param peer non-null; peer credentials 
    41.     * @throws ZygoteSecurityException 
    42.     */  
    43.    private static void applyseInfoSecurityPolicy(  
    44.            Arguments args, Credentials peer, String peerSecurityContext)  
    45.            throws ZygoteSecurityException {  
    46.        int peerUid = peer.getUid();  
    47.   
    48.        if (args.seInfo == null) {  
    49.            // nothing to check  
    50.            return;  
    51.        }  
    52.   
    53.        if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) {  
    54.            // All peers with UID other than root or SYSTEM_UID  
    55.            throw new ZygoteSecurityException(  
    56.                    "This UID may not specify SEAndroid info.");  
    57.        }  
    58.   
    59.        boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,  
    60.                                                     peerSecurityContext,  
    61.                                                     "zygote",  
    62.                                                     "specifyseinfo");  
    63.        if (!allowed) {  
    64.            throw new ZygoteSecurityException(  
    65.                    "Peer may not specify SEAndroid info");  
    66.        }  
    67.   
    68.        return;  
    69.    }  



    理所当然的,在启动一个新的进程时,frameworks/base/core/java/android/os/Process.java中也会加入SEAndroid信息seInfo。 

  • 相关阅读:
    ASP.NET中的状态保持(转载)
    Win7系统下VS2008安装SP1补丁解决JQuery无智能提示的问题
    合并多个List<T>类型并通过LINQ按指定属性排序
    ASP.NET状态保持:ViewState
    第一部分 CLR基础:第1章 CLR的执行模型
    Oracle存储过程知识汇总
    ASP.NET中Button控件的CommandName和CommandArgument属性用法
    PL/SQL Developer使用
    ASP.NET常用代码汇总
    PL/SQL Developer中文注释乱码的解决办法
  • 原文地址:https://www.cnblogs.com/LCGIS/p/3341572.html
Copyright © 2011-2022 走看看