Android 安全攻防(三): SEAndroid Zygote


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


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

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。

/* native public static int forkAndSpecialize(int uid, int gid,* int[] gids, int debugFlags, String seInfo, String niceName);*/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,用于定义新进程名。

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

#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/** Set SELinux security context.** Returns 0 on success, -1 on failure.*/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参数传递。

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);    /**     * Forks a new VM instance.     * @deprecated use {@link Zygote#forkAndSpecialize(int, int, int[], int, int[][])}     */    @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函数进一步处理了。

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

 /**     * Applies zygote security policy.     * Based on the credentials of the process issuing a zygote command:     * <ol>     * <li> uid 0 (root) may specify --invoke-with to launch Zygote with a     * wrapper command.     * <li> Any other uid may not specify any invoke-with argument.     * </ul>     *     * @param args non-null; zygote spawner arguments     * @param peer non-null; peer credentials     * @throws ZygoteSecurityException     */    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");            }        }    }    /**     * Applies zygote security policy for SEAndroid information.     *     * @param args non-null; zygote spawner arguments     * @param peer non-null; peer credentials     * @throws ZygoteSecurityException     */    private static void applyseInfoSecurityPolicy(            Arguments args, Credentials peer, String peerSecurityContext)            throws ZygoteSecurityException {        int peerUid = peer.getUid();        if (args.seInfo == null) {            // nothing to check            return;        }        if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) {            // All peers with UID other than root or SYSTEM_UID            throw new ZygoteSecurityException(                    "This UID may not specify SEAndroid info.");        }        boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,                                                     peerSecurityContext,                                                     "zygote",                                                     "specifyseinfo");        if (!allowed) {            throw new ZygoteSecurityException(                    "Peer may not specify SEAndroid info");        }        return;    }


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






更多相关文章

  1. Android(安卓)启动过程
  2. Android(安卓)kernel code merged into mainline
  3. Android(安卓)3.0 r1 API中文文档(106) ―― SimpleCursorAdapte
  4. Android开发者指南(8) ―― What is Android?
  5. Android(安卓)笔试/面试,常见问题整理
  6. Android(安卓)Activity概述
  7. Android(安卓)Binder
  8. android基本架构
  9. 2013.09.02——— android 处理音频焦点

随机推荐

  1. android studio 导入 Launcher3 的一些问
  2. Android(安卓)常见知识整理(1)
  3. android 设置全屏的两种方法
  4. Android(安卓)Audio延迟(latency)
  5. Android的消息机制(异步处理)
  6. Android——eclipse共享library以及导出j
  7. 2014.01.13(2) ——— android listview fa
  8. [Android开发常见问题-21] Android(安卓)
  9. Android(安卓)PreferenceActivity的介绍
  10. Android禁止Menu菜单键长按,(Android菜单形