Android安全攻防(三):SEAndroid Zygote
Android安全攻防(三):SEAndroid Zygote
Androidシステムでは、すべてのアプリケーションプロセス、およびシステムサービスプロセスSystemServerがZygoteによってforkを生み出しています.Zygoteのnative取得主な研究dalvik/vm/native/dalvik_system_Zygote.cpp,SEAndroidはアプリケーションリソースアクセス権限を管理し,dalvik全体に対しても,ここで動作する手足である.
まずは投げ出したDalvikNativeMethod dvm_を見てdalvik_system_Zygoteは、オリジナルAndroidと比較して、nativeForkAndSpecializeで2つのStringタイプのパラメータを追加しました.
では、この2つのパラメータは何ですか?追いかけ続ける
forkAndSpecialize.
入力された2つのパラメータを追加すると、1つはseInfoであり、新しいプロセスを定義するSEAndroid情報であり、1つはniceNameであり、新しいプロセス名を定義するために使用されることがわかります.
static pid_t forkAndSpecializeCommon(const u 4*args,bool isSystemServer)では、SEAndroidにはSELinuxセキュリティコンテキストコードセグメント、seInfo、niceNameの設定が追加されています.
SELinuxセキュリティコンテキストメソッドの実装を設定します.
さらに上の階に行くとlibcore/dalvik/src/main/java/dalvik/system/Zygote.JAva,Zygoteクラスのカプセル化,forkAndSpecializeメソッドにseInfoとniceNameパラメータ伝達を追加する.
Androidアプリケーションの起動プロセスは言うまでもなく、ZygoteConnectionオブジェクトがsocket接続のために確立すると、次にZygoteConnectionが呼び出される.runOnce関数はさらに処理された.
ソースの場所:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.JAvaでは、SEAndroidがzygoteセキュリティポリシー関数を追加し、runOnceで呼び出します.
当然、新しいプロセスを開始するとframeworks/base/core/java/android/os/process.JAvaにもSEAndroid情報seInfoが入ります.
Androidシステムでは、すべてのアプリケーションプロセス、およびシステムサービスプロセスSystemServerがZygoteによってforkを生み出しています.Zygoteのnative取得主な研究dalvik/vm/native/dalvik_system_Zygote.cpp,SEAndroidはアプリケーションリソースアクセス権限を管理し,dalvik全体に対しても,ここで動作する手足である.
まずは投げ出したDalvikNativeMethod dvm_を見てdalvik_system_Zygoteは、オリジナルAndroidと比較して、nativeForkAndSpecializeで2つの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 },
}
では、この2つのパラメータは何ですか?追いかけ続ける
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つのパラメータを追加すると、1つはseInfoであり、新しいプロセスを定義するSEAndroid情報であり、1つはniceNameであり、新しいプロセス名を定義するために使用されることがわかります.
static pid_t forkAndSpecializeCommon(const u 4*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
", 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が入ります.